diff options
Diffstat (limited to 'third_party/heimdal/lib/hx509')
178 files changed, 45491 insertions, 0 deletions
diff --git a/third_party/heimdal/lib/hx509/ChangeLog b/third_party/heimdal/lib/hx509/ChangeLog new file mode 100644 index 0000000..d00f1f3 --- /dev/null +++ b/third_party/heimdal/lib/hx509/ChangeLog @@ -0,0 +1,2749 @@ +2008-07-14 Love Hörnquist Åstrand <lha@kth.se> + + * hxtool.c: Break out print_eval_types(). + +2008-06-21 Love Hörnquist Åstrand <lha@kth.se> + + * ks_p12.c: pass in time_now to unevelope + + * cms.c: Pass in time_now to unevelope, us verify context time in + verify_signed. + +2008-05-23 Love Hörnquist Åstrand <lha@kth.se> + + * hx_locl.h: Include <limits.h> for TYPE_MAX defines. + +2008-04-29 Love Hörnquist Åstrand <lha@it.su.se> + + * sel-lex.l: Use _hx509_sel_yyerror() instead of error_message(). + +2008-04-20 Love Hörnquist Åstrand <lha@it.su.se> + + * sel-lex.l: Include <config.h> + +2008-04-17 Love Hörnquist Åstrand <lha@it.su.se> + + * Makefile.am: Update make-proto usage. + +2008-04-15 Love Hörnquist Åstrand <lha@it.su.se> + + * ca.c: BasicConstraints.pathLenConstraint unsigned int. + + * sel-lex.l: Prefix sel_error with _hx509_ since its global on + platforms w/o symbol versioning. + + * sel.h: rename yyerror to sel_yyerror in the whole library, not + just the lexer + + * sel-lex.l: rename yyerror to sel_yyerror in the whole library, + not just the lexer + +2008-04-14 Love Hörnquist Åstrand <lha@it.su.se> + + * sel-lex.l: Rename yyerror to sel_yyerror and make it static. + +2008-04-08 Love Hörnquist Åstrand <lha@it.su.se> + + * hx509.h: Make self-standing by including missing files. + +2008-04-07 Love Hörnquist Åstrand <lha@it.su.se> + + * ks_p11.c: Use unsigned where appropriate. + + * softp11.c: call va_start before using vsnprintf. + + * crypto.c: make refcount slightly more sane. + + * keyset.c: make refcount slightly more sane. + + * cert.c: make refcount slightly more sane. + +2008-03-19 Love Hörnquist Åstrand <lha@it.su.se> + + * test_nist2.in: Try to find unzip. + +2008-03-16 Love Hörnquist Åstrand <lha@it.su.se> + + * version-script.map: add missing symbols + + * spnego: Make delegated credentials delegated directly, Oleg + Sharoiko pointed out that it always didnt work with the old + code. Also add som missing cred and context pass-thou functions in + the SPNEGO layer. + +2008-03-14 Love Hörnquist Åstrand <lha@it.su.se> + + * rename to be more consistent, export for teting + + * Add language to support querying certificates to find a + match. Support constructs like "1.3.6.1.5.2.3.5" IN + %{certificate.eku} AND %{certificate.subject} TAILMATCH "C=SE". + +2008-02-26 Love Hörnquist Åstrand <lha@it.su.se> + + * version-script.map: add hx509_pem_read + + * hxtool-commands.in: Add --pem to cms-verify-sd. + + * test_cms.in: Test verifying PEM signature files. + + * hxtool.c: Support verifying PEM signature files. + +2008-02-25 Love Hörnquist Åstrand <lha@it.su.se> + + * Makefile.am: libhx509_la_OBJECTS depends on hx_locl.h + +2008-02-11 Love Hörnquist Åstrand <lha@it.su.se> + + * Use ldap-prep (with libwind) to compare names + +2008-01-27 Love Hörnquist Åstrand <lha@it.su.se> + + * cert.c (hx509_query_match_eku): update to support the NULL + eku (reset), clearify the old behaivor with regards repetitive + calls. + + * Add matching on EKU, validate EKUs, add hxtool matching glue, + add check. Adapted from pach from Tim Miller of Mitre + +2008-01-21 Love Hörnquist Åstrand <lha@it.su.se> + + * test_soft_pkcs11.c: use func for more C_ functions. + +2008-01-18 Love Hörnquist Åstrand <lha@it.su.se> + + * version-script.map: Export hx509_free_error_string(). + +2008-01-17 Love Hörnquist Åstrand <lha@it.su.se> + + * version-script.map: only export C_GetFunctionList + + * test_soft_pkcs11.c: use C_GetFunctionList + + * softp11.c: fix comment, remove label. + + * softp11.c: Add option app-fatal to control if softtoken should + abort() on erroneous input from applications. + +2008-01-16 Love Hörnquist Åstrand <lha@it.su.se> + + * test_pkcs11.in: Test password less certificates too + + * keyset.c: document HX509_CERTS_UNPROTECT_ALL + + * ks_file.c: Support HX509_CERTS_UNPROTECT_ALL. + + * hx509.h: Add HX509_CERTS_UNPROTECT_ALL. + + * test_soft_pkcs11.c: Only log in if needed. + +2008-01-15 Love Hörnquist Åstrand <lha@it.su.se> + + * softp11.c: Support PINs to login to the store. + + * Makefile.am: add java pkcs11 test + + * test_java_pkcs11.in: first version of disable java test + + * softp11.c: Drop unused stuff. + + * cert.c: Spelling, Add hx509_cert_get_SPKI_AlgorithmIdentifier, + remove unused stuff, add hx509_context to some functions. + + * softp11.c: Add more glue to figure out what keytype this + certificate is using. + +2008-01-14 Love Hörnquist Åstrand <lha@it.su.se> + + * test_pkcs11.in: test debug + + * Add a PKCS11 provider supporting signing and verifing sigatures. + +2008-01-13 Love Hörnquist Åstrand <lha@it.su.se> + + * version-script.map: Replace hx509_name_to_der_name with + hx509_name_binary. + + * print.c: make print_func static + +2007-12-26 Love Hörnquist Åstrand <lha@it.su.se> + + * print.c: doxygen + + * env.c: doxygen + + * doxygen.c: add more groups + + * ca.c: doxygen. + +2007-12-17 Love Hörnquist Åstrand <lha@it.su.se> + + * ca.c: doxygen + +2007-12-16 Love Hörnquist Åstrand <lha@it.su.se> + + * error.c: doxygen + +2007-12-15 Love Hörnquist Åstrand <lha@it.su.se> + + * More documentation + + * lock.c: Add page referance + + * keyset.c: some more documentation. + + * cms.c: Doxygen documentation. + +2007-12-11 Love Hörnquist Åstrand <lha@it.su.se> + + * *.[ch]: More documentation + +2007-12-09 Love Hörnquist Åstrand <lha@it.su.se> + + * handle refcount on NULL. + + * test_nist_pkcs12.in: drop echo -n, doesn't work with posix sh + +2007-12-08 Love Hörnquist Åstrand <lha@it.su.se> + + * test_nist2.in: Print that this is version 2 of the tests + + * test_nist.in: Drop printing of $id. + + * hx509.h: Add HX509_VHN_F_ALLOW_NO_MATCH. + + * name.c: spelling. + + * cert.c: make work the doxygen. + + * name.c: fix doxygen compiling. + + * Makefile.am: add doxygen.c + + * doxygen.c: Add doxygen main page. + + * cert.c: Add doxygen. + + * revoke.c (_hx509_revoke_ref): new function. + +2007-11-16 Love Hörnquist Åstrand <lha@it.su.se> + + * ks_keychain.c: Check if SecKeyGetCSPHandle needs prototype. + +2007-08-16 Love Hörnquist Åstrand <lha@it.su.se> + + * data/nist-data: Make work on case senstive filesystems too. + +2007-08-09 Love Hörnquist Åstrand <lha@it.su.se> + + * cert.c: match rfc822 contrains better, provide better error + strings. + +2007-08-08 Love Hörnquist Åstrand <lha@it.su.se> + + * cert.c: "self-signed doesn't count" doesn't apply to trust + anchor certificate. make trust anchor check consistant. + + * revoke.c: make compile. + + * revoke.c (verify_crl): set error strings. + + * revoke.c (verify_crl): handle with the signer is the + CRLsigner (shortcut). + + * cert.c: Fix NC, comment on how to use _hx509_check_key_usage. + +2007-08-03 Love Hörnquist Åstrand <lha@it.su.se> + + * test_nist2.in, Makefile, test/nist*: Add nist pkits tests. + + * revoke.c: Update to use CERT_REVOKED error, shortcut out of OCSP + checking when OCSP reply is a revocation reply. + + * hx509_err.et: Make CERT_REVOKED error OCSP/CRL agnostic. + + * name.c (_hx509_Name_to_string): make printableString handle + space (0x20) diffrences as required by rfc3280. + + * revoke.c: Search for the right issuer when looking for the + issuer of the CRL signer. + +2007-08-02 Love Hörnquist Åstrand <lha@it.su.se> + + * revoke.c: Handle CRL signing certificate better, try to not + revalidate invalid CRLs over and over. + +2007-08-01 Love Hörnquist Åstrand <lha@it.su.se> + + * cms.c: remove stale comment. + + * test_nist.in: Unpack PKITS_data.zip and run tests. + + * test_nist_cert.in: Adapt to new nist pkits framework. + + * test_nist_pkcs12.in: Adapt to new nist pkits framework. + + * Makefile.am: clean PKITS_data + +2007-07-16 Love Hörnquist Åstrand <lha@it.su.se> + + * Makefile.am: Add version-script.map to EXTRA_DIST + +2007-07-12 Love Hörnquist Åstrand <lha@it.su.se> + + * Makefile.am: Add depenency on asn1_compile for asn1 built files. + +2007-07-10 Love Hörnquist Åstrand <lha@it.su.se> + + * peer.c: update (c), indent. + + * Makefile.am: New library version. + +2007-06-28 Love Hörnquist Åstrand <lha@it.su.se> + + * ks_p11.c: Add sha2 types. + + * ref/pkcs11.h: Sync with scute. + + * ref/pkcs11.h: Add sha2 CKM's. + + * print.c: Print authorityInfoAccess. + + * cert.c: Rename proxyCertInfo oid. + + * ca.c: Rename proxyCertInfo oid. + + * print.c: Rename proxyCertInfo oid. + +2007-06-26 Love Hörnquist Åstrand <lha@it.su.se> + + * test_ca.in: Adapt to new request handling. + + * req.c: Allow export some of the request parameters. + + * hxtool-commands.in: Adapt to new request handling. + + * hxtool.c: Adapt to new request handling. + + * test_req.in: Adapt to new request handling. + + * version-script.map: Add initialize_hx_error_table_r. + + * req.c: Move _hx509_request_print here. + + * hxtool.c: use _hx509_request_print + + * version-script.map: Export more crap^W semiprivate functions. + + * hxtool.c: don't _hx509_abort + + * version-script.map: add missing ; + +2007-06-25 Love Hörnquist Åstrand <lha@it.su.se> + + * cms.c: Use hx509_crypto_random_iv. + + * crypto.c: Split out the iv creation from hx509_crypto_encrypt + since _hx509_pbe_encrypt needs to use the iv from the s2k + function. + + * test_cert.in: Test PEM and DER FILE writing functionallity. + + * ks_file.c: Add writing DER certificates. + + * hxtool.c: Update to new hx509_pem_write(). + + * test_cms.in: test creation of PEM signeddata. + + * hx509.h: PEM struct/function declarations. + + * ks_file.c: Use PEM encoding/decoding functions. + + * file.c: PEM encode/decoding functions. + + * ks_file.c: Use hx509_pem_write. + + * version-script.map: Export some semi-private functions. + + * hxtool.c: Enable writing out signed data as a pem attachment. + + * hxtool-commands.in (cms-create-signed): add --pem + + * file.c (hx509_pem_write): Add. + + * test_ca.in: Issue and test null subject cert. + + * cert.c: Match is first component is in a CN=. + + * test_ca.in: Test hostname if first CN. + + * Makefile.am: Add version script. + + * version-script.map: Limited exported symbols. + + * test_ca.in: test --hostname. + + * test_chain.in: test max-depth + + * hx509.h: fixate HX509_HN_HOSTNAME at 0. + + * hxtool-commands.in: add --hostname add --max-depth + + * cert.c: Verify hostname and max-depth. + + * hxtool.c: Verify hostname and test max-depth. + +2007-06-24 Love Hörnquist Åstrand <lha@it.su.se> + + * test_cms.in: Test --id-by-name. + + * hxtool-commands.in: add cms-create-sd --id-by-name + + * hxtool.c: Use HX509_CMS_SIGATURE_ID_NAME. + + * cms.c: Implement and use HX509_CMS_SIGATURE_ID_NAME. + + * hx509.h: Add HX509_CMS_SIGATURE_ID_NAME, use subject name for + CMS.Identifier. hx509_hostname_type: add hostname type for + matching. + + * cert.c (match_general_name): more strict rfc822Name matching. + (hx509_verify_hostname): add hostname type for matching. + +2007-06-19 Love Hörnquist Åstrand <lha@it.su.se> + + * hxtool.c: Make compile again. + + * hxtool.c: Added peap-server for to make windows peap clients + happy. + + * hxtool.c: Unify parse_oid code. + + * hxtool.c: Implement --content-type. + + * hxtool-commands.in: Add content-type. + + * test_cert.in: more cert and keyset tests. + +2007-06-18 Love Hörnquist Åstrand <lha@it.su.se> + + * revoke.c: Avoid stomping on NULL. + + * revoke.c: Avoid reusing i. + + * cert.c: Provide __attribute__ for _hx509_abort. + + * ks_file.c: Fail if not finding iv. + + * keyset.c: Avoid useing freed memory. + + * crypto.c: Free memory in failure case. + + * crypto.c: Free memory in failure case. + +2007-06-12 Love Hörnquist Åstrand <lha@it.su.se> + + * *.c: Add hx509_cert_init_data and use everywhere + + * hx_locl.h: Now that KEYCHAIN:system-anchors is fast again, use + that. + + * ks_keychain.c: Implement trust anchor support with + SecTrustCopyAnchorCertificates. + + * keyset.c: Set ref to 1 for the new object. + + * cert.c: Fix logic for allow_default_trust_anchors + + * keyset.c: Add refcounting to keystores. + + * cert.c: Change logic for default trust anchors, make it be + either default trust anchor, the user supplied, or non at all. + +2007-06-08 Love Hörnquist Åstrand <lha@it.su.se> + + * Makefile.am: Add data/j.pem. + + * Makefile.am: Add test_windows.in. + +2007-06-06 Love Hörnquist Åstrand <lha@it.su.se> + + * ks_keychain.c: rename functions, leaks less memory and more + paranoia. + + * test_cms.in: Test cms peer-alg. + + * crypto.c (rsa_create_signature): make oid_id_pkcs1_rsaEncryption + mean rsa-with-sha1 but oid oid_id_pkcs1_rsaEncryption in algorithm + field. XXX should probably use another algorithmIdentifier for + this. + + * peer.c: Make free function return void. + + * cms.c (hx509_cms_create_signed_1): Use hx509_peer_info to select + the signature algorithm too. + + * hxtool-commands.in: Add cms-create-sd --peer-alg. + + * req.c: Use _hx509_crypto_default_sig_alg. + + * test_windows.in: Create crl, because everyone needs one. + + * Makefile.am: add wcrl.crl + +2007-06-05 Love Hörnquist Åstrand <lha@it.su.se> + + * hx_locl.h: Disable KEYCHAIN for now, its slow. + + * cms.c: When we are not using pkcs7-data, avoid seing + signedAttributes since some clients get upset by that (pkcs7 based + or just plain broken). + + * ks_keychain.c: Provide rsa signatures. + + * ks_keychain.c: Limit the searches to the selected keychain. + + * ks_keychain.c: include -framework Security specific header files + after #ifdef + + * ks_keychain.c: Find and attach private key (does not provide + operations yet though). + + * ks_p11.c: Prefix rsa method with p11_ + + * ks_keychain.c: Allow opening a specific chain, making "system" + special and be the system X509Anchors file. By not specifing any + keychain ("KEYCHAIN:"), all keychains are probed. + +2007-06-04 Love Hörnquist Åstrand <lha@it.su.se> + + * hxtool.c (verify): Friendlier error message. + + * cert.c: Read in and use default trust anchors if they exists. + + * hx_locl.h: Add concept of default_trust_anchors. + + * ks_keychain.c: Remove err(), remove extra empty comment, fix + _iter function. + + * error.c (hx509_get_error_string): if the error code is not the + one we expect, punt and use the default com_err/strerror string + instead. + + * keyset.c (hx509_certs_merge): its ok to merge in the NULL set of + certs. + + * test_windows.in: Fix status string. + + * ks_p12.c (store_func): free whole CertBag, not just the data + part. + + * print.c: Check that the self-signed cert is really self-signed. + + * print.c: Use selfsigned for CRL DP whine, tell if its a + self-signed. + + * print.c: Whine if its a non CA/proxy and doesn't have CRL DP. + + * ca.c: Add cRLSign to CA certs. + + * cert.c: Register NULL and KEYCHAIN. + + * ks_null.c: register the NULL keystore. + + * Makefile.am: Add ks_keychain.c and related libs. + + * test_crypto.in: Print certificate with utf8. + + * print.c: Leak less memory. + + * hxtool.c: Leak less memory. + + * print.c: Leak less memory, use functions that does same but + more. + + * name.c (quote_string): don't sign extend the (signed) char to + avoid printing too much, add an assert to check that we didn't + overrun the buffer. + + * name.c: Use right element out of the CHOICE for printableString + and utf8String + + * ks_keychain.c: Certificate only KeyChain backend. + + * name.c: Reset name before parsing it. + +2007-06-03 Love Hörnquist Åstrand <lha@it.su.se> + + * revoke.c (hx509_crl_*): fix sizeof() mistakes to fix memory + corruption. + + * hxtool.c: Add lifetime to crls. + + * hxtool-commands.in: Add lifetime to crls. + + * revoke.c: Add lifetime to crls. + + * test_ca.in: More crl checks. + + * revoke.c: Add revoking certs. + + * hxtool-commands.in: argument is certificates.. for crl-sign + + * hxtool.c (certificate_copy): free lock + + * revoke.c: Fix hx509_set_error_string calls, add + hx509_crl_add_revoked_certs(), implement hx509_crl_{alloc,free}. + + * hxtool.c (crl_sign): free lock + + * cert.c (hx509_context_free): free querystat + +2007-06-02 Love Hörnquist Åstrand <lha@it.su.se> + + * test_chain.in: test ocsp-verify + + * revoke.c (hx509_ocsp_verify): explain what its useful for and + provide sane error message. + + * hx509_err.et: New error code, CERT_NOT_IN_OCSP + + * hxtool.c: New command ocsp-verify, check if ocsp contains all + certs and are valid (exist and non expired). + + * hxtool-commands.in: New command ocsp-verify. + +2007-06-01 Love Hörnquist Åstrand <lha@it.su.se> + + * test_ca.in: Create crl and verify that is works. + + * hxtool.c: Sign CRL command. + + * hx509.h: Add hx509_crl. + + * hxtool-commands.in: Add crl-sign commands. + + * revoke.c: Support to generate an empty CRL. + + * tst-crypto-select2: Switched default types. + + * tst-crypto-select1: Switched default types. + + * ca.c: Use default AlgorithmIdentifier. + + * cms.c: Use default AlgorithmIdentifier. + + * crypto.c: Provide default AlgorithmIdentifier and use them. + + * hx_locl.h: Provide default AlgorithmIdentifier. + + * keyset.c (hx509_certs_find): collects stats for queries. + + * cert.c: Sort and print more info. + + * hx_locl.h: Add querystat to hx509_context. + + * test_*.in: sprinle stat saveing + + * Makefile.am: Add stat and objdir. + + * collector.c (_hx509_collector_alloc): return error code instead + of pointer. + + * hxtool.c: Add statistic hook. + + * ks_file.c: Update _hx509_collector_alloc prototype. + + * ks_p12.c: Update _hx509_collector_alloc prototype. + + * ks_p11.c: Update _hx509_collector_alloc prototype. + + * hxtool-commands.in: Add statistics hook. + + * cert.c: Statistics printing. + + * ks_p12.c: plug memory leak + + * ca.c (hx509_ca_tbs_add_crl_dp_uri): plug memory leak + +2007-05-31 Love Hörnquist Åstrand <lha@it.su.se> + + * print.c: print utf8 type SAN's + + * Makefile.am: Fix windows client cert name. + + * test_windows.in: Add crl-uri for the ee certs. + + * print.c: Printf formating. + + * ca.c: Add glue for adding CRL dps. + + * test_ca.in: Readd the crl adding code, it works (somewhat) now. + + * print.c: Fix printing of CRL DPnames (I hate IMPLICIT encoded + structures). + + * hxtool-commands.in: make ca and alias of certificate-sign + +2007-05-30 Love Hörnquist Åstrand <lha@it.su.se> + + * crypto.c (hx509_crypto_select): copy AI to the right place. + + * hxtool-commands.in: Add ca --ms-upn. + + * hxtool.c: add --ms-upn and add more EKU's for pk-init client. + + * ca.c: Add hx509_ca_tbs_add_san_ms_upn and refactor code. + + * test_crypto.in: Resurect killed e. + + * test_crypto.in: check for aes256-cbc + + * tst-crypto-select7: check for aes256-cbc + + * test_windows.in: test windows stuff + + * hxtool.c: add ca --domain-controller option, add secret key + option to avaible. + + * ca.c: Add hx509_ca_tbs_set_domaincontroller. + + * hxtool-commands.in: add ca --domain-controller + + * hxtool.c: hook for testing secrety key algs + + * crypto.c: Add selection code for secret key crypto. + + * hx509.h: Add HX509_SELECT_SECRET_ENC. + +2007-05-13 Love Hörnquist Åstrand <lha@it.su.se> + + * ks_p11.c: add more mechtypes + +2007-05-10 Love Hörnquist Åstrand <lha@it.su.se> + + * print.c: Indent. + + * hxtool-commands.in: add test-crypto command + + * hxtool.c: test crypto command + + * cms.c (hx509_cms_create_signed_1): if no eContentType is given, + use pkcs7-data. + + * print.c: add Netscape cert comment + + * crypto.c: Try both the empty password and the NULL + password (nothing vs the octet string \x00\x00). + + * print.c: Add some US Fed PKI oids. + + * ks_p11.c: Add some more hashes. + +2007-04-24 Love Hörnquist Åstrand <lha@it.su.se> + + * hxtool.c (crypto_select): stop memory leak + +2007-04-19 Love Hörnquist Åstrand <lha@it.su.se> + + * peer.c (hx509_peer_info_free): free memory used too + + * hxtool.c (crypto_select): only free peer if it was used. + +2007-04-18 Love Hörnquist Åstrand <lha@it.su.se> + + * hxtool.c: free template + + * ks_mem.c (mem_free): free key array too + + * hxtool.c: free private key and tbs + + * hxtool.c (hxtool_ca): free signer + + * hxtool.c (crypto_available): free peer too. + + * ca.c (get_AuthorityKeyIdentifier): leak less memory + + * hxtool.c (hxtool_ca): free SPKI + + * hxtool.c (hxtool_ca): free cert + + * ks_mem.c (mem_getkeys): allocate one more the we have elements + so its possible to store the NULL pointer at the end. + +2007-04-16 Love Hörnquist Åstrand <lha@it.su.se> + + * Makefile.am: CLEANFILES += cert-null.pem cert-sub-ca2.pem + +2007-02-05 Love Hörnquist Åstrand <lha@it.su.se> + + * ca.c: Disable CRLDistributionPoints for now, its IMPLICIT code + in the asn1 parser. + + * print.c: Add some more \n's. + +2007-02-03 Love Hörnquist Åstrand <lha@it.su.se> + + * file.c: Allow mapping using heim_octet_string. + + * hxtool.c: Add options to generate detached signatures. + + * cms.c: Add flags to generate detached signatures. + + * hx509.h: Flag to generate detached signatures. + + * test_cms.in: Support detached sigatures. + + * name.c (hx509_general_name_unparse): unparse the other + GeneralName nametypes. + + * print.c: Use less printf. Use hx509_general_name_unparse. + + * cert.c: Fix printing and plug leak-on-error. + +2007-01-31 Love Hörnquist Åstrand <lha@it.su.se> + + * test_ca.in: Add test for ca --crl-uri. + + * hxtool.c: Add ca --crl-uri. + + * hxtool-commands.in: add ca --crl-uri + + * ca.c: Code to set CRLDistributionPoints in certificates. + + * print.c: Check CRLDistributionPointNames. + + * name.c (hx509_general_name_unparse): function for unparsing + GeneralName, only supports GeneralName.URI + + * cert.c (is_proxy_cert): free info if we wont return it. + +2007-01-30 Love Hörnquist Åstrand <lha@it.su.se> + + * hxtool.c: Try to help how to use this command. + +2007-01-21 Love Hörnquist Åstrand <lha@it.su.se> + + * switch to sha256 as default digest for signing + +2007-01-20 Love Hörnquist Åstrand <lha@it.su.se> + + * test_ca.in: Really test sub-ca code, add basic constraints tests + +2007-01-17 Love Hörnquist Åstrand <lha@it.su.se> + + * Makefile.am: Fix makefile problem. + +2007-01-16 Love Hörnquist Åstrand <lha@it.su.se> + + * hxtool.c: Set num of bits before we generate the key. + +2007-01-15 Love Hörnquist Åstrand <lha@it.su.se> + + * cms.c (hx509_cms_create_signed_1): use hx509_cert_binary + + * ks_p12.c (store_func): use hx509_cert_binary + + * ks_file.c (store_func): use hx509_cert_binary + + * cert.c (hx509_cert_binary): return binary encoded + certificate (DER format) + +2007-01-14 Love Hörnquist Åstrand <lha@it.su.se> + + * ca.c (hx509_ca_tbs_subject_expand): new function. + + * name.c (hx509_name_expand): if env is NULL, return directly + + * test_ca.in: test template handling + + * hx509.h: Add template flags. + + * Makefile.am: clean out new files + + * hxtool.c: Add certificate template processing, fix hx509_err + usage. + + * hxtool-commands.in: Add certificate template processing. + + * ca.c: Add certificate template processing. Fix return messages + from hx509_ca_tbs_add_eku. + + * cert.c: Export more stuff from certificate. + +2007-01-13 Love Hörnquist Åstrand <lha@it.su.se> + + * ca.c: update (c) + + * ca.c: (hx509_ca_tbs_add_eku): filter out dups. + + * hxtool.c: Add type email and add email eku when using option + --email. + + * Makefile.am: add env.c + + * name.c: Remove abort, add error handling. + + * test_name.c: test name expansion + + * name.c: add hx509_name_expand + + * env.c: key-value pair help functions + +2007-01-12 Love Hörnquist Åstrand <lha@it.su.se> + + * ca.c: Don't issue certs with subject DN that is NULL and have no + SANs + + * print.c: Fix previous test. + + * print.c: Check there is a SAN if subject DN is NULL. + + * test_ca.in: test email, null subject dn + + * hxtool.c: Allow setting parameters to private key generation. + + * hx_locl.h: Allow setting parameters to private key generation. + + * crypto.c: Allow setting parameters to private key generation. + + * hxtool.c (eval_types): add jid if user gave one + + * hxtool-commands.in (certificate-sign): add --jid + + * ca.c (hx509_ca_tbs_add_san_jid): Allow adding + id-pkix-on-xmppAddr OtherName. + + * print.c: Print id-pkix-on-xmppAddr OtherName. + +2007-01-11 Love Hörnquist Åstrand <lha@it.su.se> + + * no random, no RSA/DH tests + + * hxtool.c (info): print status of random generator + + * Makefile.am: remove files created by tests + + * error.c: constify + + * name.c: constify + + * revoke.c: constify + + * hx_locl.h: constify + + * keyset.c: constify + + * ks_p11.c: constify + + * hx_locl.h: make printinfo char * argument const. + + * cms.c: move _hx509_set_digest_alg from cms.c to crypto.c since + its only used there. + + * crypto.c: remove no longer used stuff, move set_digest_alg here + from cms.c since its only used here. + + * Makefile.am: add data/test-nopw.p12 to EXTRA_DIST + +2007-01-10 Love Hörnquist Åstrand <lha@it.su.se> + + * print.c: BasicConstraints vs criticality bit is complicated and + not really possible to evaluate on its own, silly RFC3280. + + * ca.c: Make basicConstraints critical if this is a CA. + + * print.c: fix the version vs extension test + + * print.c: More validation checks. + + * name.c (hx509_name_cmp): add + +2007-01-09 Love Hörnquist Åstrand <lha@it.su.se> + + * ks_p11.c (collect_private_key): Missing CKA_MODULUS is ok + too (XXX why should these be fetched given they are not used). + + * test_ca.in: rename all files to PEM files, since that is what + they are. + + * hxtool.c: copy out the key with the self signed CA cert + + * Factor out private key operation out of the signing, operations, + support import, export, and generation of private keys. Add + support for writing PEM and PKCS12 files with private keys in them. + + * data/gen-req.sh: Generate a no password pkcs12 file. + +2007-01-08 Love Hörnquist Åstrand <lha@it.su.se> + + * cms.c: Check for internal ASN1 encoder error. + +2007-01-05 Love Hörnquist Åstrand <lha@it.su.se> + + * Makefile.am: Drop most of the pkcs11 files. + + * test_ca.in: test reissueing ca certificate (xxx time + validAfter). + + * hxtool.c: Allow setting serialNumber (needed for reissuing + certificates) Change --key argument to --out-key. + + * hxtool-commands.in (issue-certificate): Allow setting + serialNumber (needed for reissuing certificates), Change --key + argument to --out-key. + + * ref: Replace with Marcus Brinkmann of g10 Code GmbH pkcs11 + headerfile that is compatible with GPL (file taken from scute) + +2007-01-04 Love Hörnquist Åstrand <lha@it.su.se> + + * test_ca.in: Test to generate key and use them. + + * hxtool.c: handle other keys the pkcs10 requested keys + + * hxtool-commands.in: add generate key commands + + * req.c (_hx509_request_to_pkcs10): PKCS10 needs to have a subject + + * hxtool-commands.in: Spelling. + + * ca.c (hx509_ca_tbs_set_proxy): allow negative pathLenConstraint + to signal no limit + + * ks_file.c: Try all formats on the binary file before giving up, + this way we can handle binary rsa keys too. + + * data/key2.der: new test key + +2007-01-04 David Love <fx@gnu.org> + + * Makefile.am (hxtool_LDADD): Add libasn1.la + + * hxtool.c (pcert_verify): Fix format string. + +2006-12-31 Love Hörnquist Åstrand <lha@it.su.se> + + * hxtool.c: Allow setting path length + + * cert.c: Fix test for proxy certs chain length, it was too + restrictive. + + * data: regen + + * data/openssl.cnf: (proxy_cert) make length 0 + + * test_ca.in: Issue a long living cert. + + * hxtool.c: add --lifetime to ca command. + + * hxtool-commands.in: add --lifetime to ca command. + + * ca.c: allow setting notBefore and notAfter. + + * test_ca.in: Test generation of proxy certificates. + + * ca.c: Allow generation of proxy certificates, always include + BasicConstraints, fix error codes. + + * hxtool.c: Allow generation of proxy certificates. + + * test_name.c: make hx509_parse_name take a hx509_context. + + * name.c: Split building RDN to a separate function. + +2006-12-30 Love Hörnquist Åstrand <lha@it.su.se> + + * Makefile.am: clean test_ca files. + + * test_ca.in: test issuing self-signed and CA certificates. + + * hxtool.c: Add bits to allow issuing self-signed and CA + certificates. + + * hxtool-commands.in: Add bits to allow issuing self-signed and CA + certificates. + + * ca.c: Add bits to allow issuing CA certificates. + + * revoke.c: use new OCSPSigning. + + * ca.c: Add Subject Key Identifier. + + * ca.c: Add Authority Key Identifier. + + * cert.c: Locally export _hx509_find_extension_subject_key_id. + Handle AuthorityKeyIdentifier where only authorityCertSerialNumber + and authorityCertSerialNumber is set. + + * hxtool-commands.in: Add dnsname and rfc822 SANs. + + * test_ca.in: Test dnsname and rfc822 SANs. + + * ca.c: Add dnsname and rfc822 SANs. + + * hxtool.c: Add dnsname and rfc822 SANs. + + * test_ca.in: test adding eku, ku and san to the + certificate (https and pk-init) + + * hxtool.c: Add eku, ku and san to the certificate. + + * ca.c: Add eku, ku and san to the certificate. + + * hxtool-commands.in: Add --type and --pk-init-principal + + * ocsp.asn1: remove id-kp-OCSPSigning, its in rfc2459.asn1 now + +2006-12-29 Love Hörnquist Åstrand <lha@it.su.se> + + * ca.c: Add KeyUsage extension. + + * Makefile.am: add ca.c, add sign-certificate tests. + + * crypto.c: Add _hx509_create_signature_bitstring. + + * hxtool-commands.in: Add the sign-certificate tool. + + * hxtool.c: Add the sign-certificate tool. + + * cert.c: Add HX509_QUERY_OPTION_KU_KEYCERTSIGN. + + * hx509.h: Add hx509_ca_tbs and HX509_QUERY_OPTION_KU_KEYCERTSIGN. + + * test_ca.in: Basic test of generating a pkcs10 request, signing + it and verifying the chain. + + * ca.c: Naive certificate signer. + +2006-12-28 Love Hörnquist Åstrand <lha@it.su.se> + + * hxtool.c: add hxtool_hex + +2006-12-22 Love Hörnquist Åstrand <lha@it.su.se> + + * Makefile.am: use top_builddir for libasn1.la + +2006-12-11 Love Hörnquist Åstrand <lha@it.su.se> + + * hxtool.c (print_certificate): print serial number. + + * name.c (no): add S=stateOrProvinceName + +2006-12-09 Love Hörnquist Åstrand <lha@it.su.se> + + * crypto.c (_hx509_private_key_assign_rsa): set a default sig alg + + * ks_file.c (try_decrypt): pass down AlgorithmIdentifier that key + uses to do sigatures so there is no need to hardcode RSA into this + function. + +2006-12-08 Love Hörnquist Åstrand <lha@it.su.se> + + * ks_file.c: Pass filename to the parse functions and use it in + the error messages + + * test_chain.in: test proxy cert (third level) + + * hx509_err.et: fix errorstring for PROXY_CERT_NAME_WRONG + + * data: regen + + * Makefile.am: EXTRA_DIST: add + data/proxy10-child-child-test.{key,crt} + + * data/gen-req.sh: Fix names and restrictions on the proxy + certificates + + * cert.c: Clairfy and make proxy cert handling work for multiple + levels, before it was too restrictive. More helpful error message. + +2006-12-07 Love Hörnquist Åstrand <lha@it.su.se> + + * cert.c (check_key_usage): tell what keyusages are missing + + * print.c: Split OtherName printing code to a oid lookup and print + function. + + * print.c (Time2string): print hour as hour not min + + * Makefile.am: CLEANFILES += test + +2006-12-06 Love Hörnquist Åstrand <lha@it.su.se> + + * Makefile.am (EXTRA_DIST): add data/pkinit-proxy* files + + * Makefile.am (EXTRA_DIST): add tst-crypto* files + + * cert.c (hx509_query_match_issuer_serial): make a copy of the + data + + * cert.c (hx509_query_match_issuer_serial): allow matching on + issuer and serial num + + * cert.c (_hx509_calculate_path): add flag to allow leaving out + trust anchor + + * cms.c (hx509_cms_create_signed_1): when building the path, omit + the trust anchors. + + * crypto.c (rsa_create_signature): Abort when signature is longer, + not shorter. + + * cms.c: Provide time to _hx509_calculate_path so we don't send no + longer valid certs to our peer. + + * cert.c (find_parent): when checking for certs and its not a + trust anchor, require time be in range. + (_hx509_query_match_cert): Add time validity-testing to query mask + + * hx_locl.h: add time validity-testing to query mask + + * test_cms.in: Tests for CMS SignedData with incomplete chain from + the signer. + +2006-11-28 Love Hörnquist Åstrand <lha@it.su.se> + + * cms.c (hx509_cms_verify_signed): specify what signature we + failed to verify + + * Makefile.am: Depend on LIB_com_err for AIX. + + * keyset.c: Remove anther strndup that causes AIX to fall over. + + * cert.c: Don't check the trust anchors expiration time since they + are transported out of band, from RFC3820. + + * cms.c: sprinkle more error strings + + * crypto.c: sprinkle more error strings + + * hxtool.c: use unsigned int as counter to fit better with the + asn1 compiler + + * crypto.c: use unsigned int as counter to fit better with the + asn1 compiler + +2006-11-27 Love Hörnquist Åstrand <lha@it.su.se> + + * cms.c: Remove trailing white space. + + * crypto.c: rewrite comment to make more sense + + * crypto.c (hx509_crypto_select): check sig_algs[j]->key_oid + + * hxtool-commands.in (crypto-available): add --type + + * crypto.c (hx509_crypto_available): let alg pass if its keyless + + * hxtool-commands.in: Expand crypto-select + + * cms.c: Rename hx509_select to hx509_crypto_select. + + * hxtool-commands.in: Add crypto-select and crypto-available. + + * hxtool.c: Add crypto-select and crypto-available. + + * crypto.c (hx509_crypto_available): use right index. + (hx509_crypto_free_algs): new function + + * crypto.c (hx509_crypto_select): improve + (hx509_crypto_available): new function + +2006-11-26 Love Hörnquist Åstrand <lha@it.su.se> + + * cert.c: Sprinkle more error string and hx509_contexts. + + * cms.c: Sprinkle more error strings. + + * crypto.c: Sprinkle error string and hx509_contexts. + + * crypto.c: Add some more comments about how this works. + + * crypto.c (hx509_select): new function. + + * Makefile.am: add peer.c + + * hxtool.c: Update hx509_cms_create_signed_1. + + * hx_locl.h: add struct hx509_peer_info + + * peer.c: Allow selection of digest/sig-alg + + * cms.c: Allow selection of a better digest using hx509_peer_info. + + * revoke.c: Handle that _hx509_verify_signature takes a context. + + * cert.c: Handle that _hx509_verify_signature takes a context. + +2006-11-25 Love Hörnquist Åstrand <lha@it.su.se> + + * cms.c: Sprinkle error strings. + + * crypto.c: Sprinkle context and error strings. + +2006-11-24 Love Hörnquist Åstrand <lha@it.su.se> + + * name.c: Handle printing and parsing raw oids in name. + +2006-11-23 Love Hörnquist Åstrand <lha@it.su.se> + + * cert.c (_hx509_calculate_path): allow to calculate optimistic + path when we don't know the trust anchors, just follow the chain + upward until we no longer find a parent or we hit the max limit. + + * cms.c (hx509_cms_create_signed_1): provide a best effort path to + the trust anchors to be stored in the SignedData packet, if find + parents until trust anchor or max length. + + * data: regen + + * data/gen-req.sh: Build pk-init proxy cert. + +2006-11-16 Love Hörnquist Åstrand <lha@it.su.se> + + * error.c (hx509_get_error_string): Put ", " between strings in + error message. + +2006-11-13 Love Hörnquist Åstrand <lha@it.su.se> + + * data/openssl.cnf: Change realm to TEST.H5L.SE + +2006-11-07 Love Hörnquist Åstrand <lha@it.su.se> + + * revoke.c: Sprinkle error strings. + +2006-11-04 Love Hörnquist Åstrand <lha@it.su.se> + + * hx_locl.h: add context variable to cmp function. + + * cert.c (hx509_query_match_cmp_func): allow setting the match + function. + +2006-10-24 Love Hörnquist Åstrand <lha@it.su.se> + + * ks_p11.c: Return less EINVAL. + + * hx509_err.et: add more pkcs11 errors + + * hx509_err.et: more error-codes + + * revoke.c: Return less EINVAL. + + * ks_dir.c: sprinkel more hx509_set_error_string + + * ks_file.c: Return less EINVAL. + + * hxtool.c: Pass in context to _hx509_parse_private_key. + + * ks_file.c: Sprinkle more hx509_context so we can return propper + errors. + + * hx509_err.et: add HX509_PARSING_KEY_FAILED + + * crypto.c: Sprinkle more hx509_context so we can return propper + errors. + + * collector.c: No more EINVAL. + + * hx509_err.et: add HX509_LOCAL_ATTRIBUTE_MISSING + + * cert.c (hx509_cert_get_base_subject): one less EINVAL + (_hx509_cert_private_decrypt): one less EINVAL + +2006-10-22 Love Hörnquist Åstrand <lha@it.su.se> + + * collector.c: indent + + * hxtool.c: Try to not leak memory. + + * req.c: clean memory before free + + * crypto.c (_hx509_private_key2SPKI): indent + + * req.c: Try to not leak memory. + +2006-10-21 Love Hörnquist Åstrand <lha@it.su.se> + + * test_crypto.in: Read 50 kilobyte random data + + * revoke.c: Try to not leak memory. + + * hxtool.c: Try to not leak memory. + + * crypto.c (hx509_crypto_destroy): free oid. + + * error.c: Clean error string on failure just to make sure. + + * cms.c: Try to not leak memory (again). + + * hxtool.c: use a sensable content type + + * cms.c: Try harder to free certificate. + +2006-10-20 Love Hörnquist Åstrand <lha@it.su.se> + + * Makefile.am: Add make check data. + +2006-10-19 Love Hörnquist Åstrand <lha@it.su.se> + + * ks_p11.c (p11_list_keys): make element of search_data[0] + constants and set them later + + * Makefile.am: Add more files. + +2006-10-17 Love Hörnquist Åstrand <lha@it.su.se> + + * ks_file.c: set ret, remember to free ivdata + +2006-10-16 Love Hörnquist Åstrand <lha@it.su.se> + + * hx_locl.h: Include <parse_bytes.h>. + + * test_crypto.in: Test random-data. + + * hxtool.c: RAND_bytes() return 1 for cryptographic strong data, + check for that. + + * Makefile.am: clean random-data + + * hxtool.c: Add random-data command, use sl_slc_help. + + * hxtool-commands.in: Add random-data. + + * ks_p12.c: Remember to release certs. + + * ks_p11.c: Remember to release certs. + +2006-10-14 Love Hörnquist Åstrand <lha@it.su.se> + + * prefix der primitives with der_ + + * lock.c: Match the prompt type PROMPT exact. + + * hx_locl.h: Drop heim_any.h + +2006-10-11 Love Hörnquist Åstrand <lha@it.su.se> + + * ks_p11.c (p11_release_module): j needs to be used as inter loop + index. From Douglas Engert. + + * ks_file.c (parse_rsa_private_key): try all passwords and + prompter. + +2006-10-10 Love Hörnquist Åstrand <lha@it.su.se> + + * test_*.in: Parameterise the invocation of hxtool, so we can make + it run under TESTS_ENVIRONMENT. From Andrew Bartlett + +2006-10-08 Love Hörnquist Åstrand <lha@it.su.se> + + * test_crypto.in: Put all test stuck at 2006-09-25 since all their + chains where valied then. + + * hxtool.c: Implement --time= option. + + * hxtool-commands.in: Add option time. + + * Makefile.am: test_name is a PROGRAM_TESTS + + * ks_p11.c: Return HX509_PKCS11_NO_SLOT when there are no slots + and HX509_PKCS11_NO_TOKEN when there are no token. For use in PAM + modules that want to detect when to use smartcard login and when + not to. Patched based on code from Douglas Engert. + + * hx509_err.et: Add new pkcs11 related errors in a new section: + keystore related error. Patched based on code from Douglas + Engert. + +2006-10-07 Love Hörnquist Åstrand <lha@it.su.se> + + * Makefile.am: Make depenency for slc built files just like + everywhere else. + + * cert.c: Add all openssl algs and init asn1 et + +2006-10-06 Love Hörnquist Åstrand <lha@it.su.se> + + * ks_file.c (parse_rsa_private_key): free type earlier. + + * ks_file.c (parse_rsa_private_key): free type after use + + * name.c (_hx509_Name_to_string): remove dup const + +2006-10-02 Love Hörnquist Åstrand <lha@it.su.se> + + * Makefile.am: Add more libs to libhx509 + +2006-10-01 Love Hörnquist Åstrand <lha@it.su.se> + + * ks_p11.c: Fix double free's, NULL ptr de-reference, and conform + better to pkcs11. From Douglas Engert. + + * ref: remove ^M, it breaks solaris 10s cc. From Harald Barth + +2006-09-19 Love Hörnquist Åstrand <lha@it.su.se> + + * test_crypto.in: Bleichenbacher bad cert from Ralf-Philipp + Weinmann and Andrew Pyshkin, pad right. + + * data: starfield test root cert and Ralf-Philipp and Andreis + correctly padded bad cert + +2006-09-15 Love Hörnquist Åstrand <lha@it.su.se> + + * test_crypto.in: Add test for yutaka certs. + + * cert.c: Add a strict rfc3280 verification flag. rfc3280 requires + certificates to have KeyUsage.keyCertSign if they are to be used + for signing of certificates, but the step in the verifiation is + optional. + + * hxtool.c: Improve printing and error reporting. + +2006-09-13 Love Hörnquist Åstrand <lha@it.su.se> + + * test_crypto.in,Makefile.am,data/bleichenbacher-{bad,good}.pem: + test bleichenbacher from eay + +2006-09-12 Love Hörnquist Åstrand <lha@it.su.se> + + * hxtool.c: Make common function for all getarg_strings and + hx509_certs_append commonly used. + + * cms.c: HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT is a negative + flag, treat it was such. + +2006-09-11 Love Hörnquist Åstrand <lha@it.su.se> + + * req.c: Use the new add_GeneralNames function. + + * hx509.h: Add HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT. + + * ks_p12.c: Adapt to new signature of hx509_cms_unenvelope. + + * hxtool.c: Adapt to new signature of hx509_cms_unenvelope. + + * cms.c: Allow passing in encryptedContent and flag. Add new flag + HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT. + +2006-09-08 Love Hörnquist Åstrand <lha@it.su.se> + + * ks_p11.c: cast void * to char * when using it for %s formating + in printf. + + * name.c: New function _hx509_Name_to_string. + +2006-09-07 Love Hörnquist Åstrand <lha@it.su.se> + + * ks_file.c: Sprinkle error messages. + + * cms.c: Sprinkle even more error messages. + + * cms.c: Sprinkle some error messages. + + * cms.c (find_CMSIdentifier): only free string when we allocated + one. + + * ks_p11.c: Don't build most of the pkcs11 module if there are no + dlopen(). + +2006-09-06 Love Hörnquist Åstrand <lha@it.su.se> + + * cms.c (hx509_cms_unenvelope): try to save the error string from + find_CMSIdentifier so we have one more bit of information what + went wrong. + + * hxtool.c: More pretty printing, make verify_signed return the + error string from the library. + + * cms.c: Try returning what certificates failed to parse or be + found. + + * ks_p11.c (p11_list_keys): fetch CKA_LABEL and use it to set the + friendlyname for the certificate. + +2006-09-05 Love Hörnquist Åstrand <lha@it.su.se> + + * crypto.c: check that there are no extra bytes in the checksum + and that the parameters are NULL or the NULL-type. All to avoid + having excess data that can be used to fake the signature. + + * hxtool.c: print keyusage + + * print.c: add hx509_cert_keyusage_print, simplify oid printing + + * cert.c: add _hx509_cert_get_keyusage + + * ks_p11.c: keep one session around for the whole life of the keyset + + * test_query.in: tests more selection + + * hxtool.c: improve pretty printing in print and query + + * hxtool{.c,-commands.in}: add selection on KU and printing to query + + * test_cms.in: Add cms test for digitalSignature and + keyEncipherment certs. + + * name.c (no): Add serialNumber + + * ks_p11.c (p11_get_session): return better error messages + +2006-09-04 Love Hörnquist Åstrand <lha@it.su.se> + + * ref: update to pkcs11 reference files 2.20 + + * ks_p11.c: add more mechflags + + * name.c (no): add OU and sort + + * revoke.c: pass context to _hx509_create_signature + + * ks_p11.c (p11_printinfo): print proper plural s + + * ks_p11.c: save the mechs supported when initing the token, print + them in printinfo. + + * hx_locl.h: Include <parse_units.h>. + + * cms.c: pass context to _hx509_create_signature + + * req.c: pass context to _hx509_create_signature + + * keyset.c (hx509_certs_info): print information about the keyset. + + * hxtool.c (pcert_print) print keystore info when --info flag is + given. + + * hxtool-commands.in: Add hxtool print --info. + + * test_query.in: Test hxtool print --info. + + * hx_locl.h (hx509_keyset_ops): add printinfo + + * crypto.c: Start to hang the private key operations of the + private key, pass hx509_context to create_checksum. + +2006-05-29 Love Hörnquist Åstrand <lha@it.su.se> + + * ks_p11.c: Iterate over all slots, not just the first/selected + one. + +2006-05-27 Love Hörnquist Åstrand <lha@it.su.se> + + * cert.c: Add release function for certifiates so backend knowns + when its no longer used. + + * ks_p11.c: Add reference counting on certifiates, push out + CK_SESSION_HANDLE from slot. + + * cms.c: sprinkle more hx509_clear_error_string + +2006-05-22 Love Hörnquist Åstrand <lha@it.su.se> + + * ks_p11.c: Sprinkle some hx509_set_error_strings + +2006-05-13 Love Hörnquist Åstrand <lha@it.su.se> + + * hxtool.c: Avoid shadowing. + + * revoke.c: Avoid shadowing. + + * ks_file.c: Avoid shadowing. + + * cert.c: Avoid shadowing. + +2006-05-12 Love Hörnquist Åstrand <lha@it.su.se> + + * lock.c (hx509_prompt_hidden): reshuffle to avoid gcc warning + + * hx509.h: Reshuffle the prompter types, remove the hidden field. + + * lock.c (hx509_prompt_hidden): return if the prompt should be + hidden or not + + * revoke.c (hx509_revoke_free): allow free of NULL. + +2006-05-11 Love Hörnquist Åstrand <lha@it.su.se> + + * ks_file.c (file_init): Avoid shadowing ret (and thus avoiding + crashing). + + * ks_dir.c: Implement DIR: caches useing FILE: caches. + + * ks_p11.c: Catch more errors. + +2006-05-08 Love Hörnquist Åstrand <lha@it.su.se> + + * crypto.c (hx509_crypto_encrypt): free correctly in error + path. From Andrew Bartlett. + + * crypto.c: If RAND_bytes fails, then we will attempt to + double-free crypt->key.data. From Andrew Bartlett. + +2006-05-05 Love Hörnquist Åstrand <lha@it.su.se> + + * name.c: Rename u_intXX_t to uintXX_t + +2006-05-03 Love Hörnquist Åstrand <lha@it.su.se> + + * TODO: More to do about the about the PKCS11 code. + + * ks_p11.c: Use the prompter from the lock function. + + * lock.c: Deal with that hx509_prompt.reply is no longer a + pointer. + + * hx509.h: Make hx509_prompt.reply not a pointer. + +2006-05-02 Love Hörnquist Åstrand <lha@it.su.se> + + * keyset.c: Sprinkle setting error strings. + + * crypto.c: Sprinkle setting error strings. + + * collector.c: Sprinkle setting error strings. + + * cms.c: Sprinkle setting error strings. + +2006-05-01 Love Hörnquist Åstrand <lha@it.su.se> + + * test_name.c: renamed one error code + + * name.c: renamed one error code + + * ks_p11.c: _hx509_set_cert_attribute changed signature + + * hxtool.c (pcert_print): use hx509_err so I can test it + + * error.c (hx509_set_error_stringv): clear errors on malloc + failure + + * hx509_err.et: Add some more errors + + * cert.c: Sprinkle setting error strings. + + * cms.c: _hx509_path_append changed signature. + + * revoke.c: changed signature of _hx509_check_key_usage + + * keyset.c: changed signature of _hx509_query_match_cert + + * hx509.h: Add support for error strings. + + * cms.c: changed signature of _hx509_check_key_usage + + * Makefile.am: ibhx509_la_files += error.c + + * ks_file.c: Sprinkel setting error strings. + + * cert.c: Sprinkel setting error strings. + + * hx_locl.h: Add support for error strings. + + * error.c: Add string error handling functions. + + * keyset.c (hx509_certs_init): pass the right error code back + +2006-04-30 Love Hörnquist Åstrand <lha@it.su.se> + + * revoke.c: Revert previous patch. + (hx509_ocsp_verify): new function that returns the expiration of + certificate in ocsp data-blob + + * cert.c: Reverse previous patch, lets do it another way. + + * cert.c (hx509_revoke_verify): update usage + + * revoke.c: Make compile. + + * revoke.c: Add the expiration time the crl/ocsp info expire + + * name.c: Add hx509_name_is_null_p + + * cert.c: remove _hx509_cert_private_sigature + +2006-04-29 Love Hörnquist Åstrand <lha@it.su.se> + + * name.c: Expose more of Name. + + * hxtool.c (main): add missing argument to printf + + * data/openssl.cnf: Add EKU for the KDC certificate + + * cert.c (hx509_cert_get_base_subject): reject un-canon proxy + certs, not the reverse + (add_to_list): constify and fix argument order to + copy_octet_string + (hx509_cert_find_subjectAltName_otherName): make work + +2006-04-28 Love Hörnquist Åstrand <lha@it.su.se> + + * data/{pkinit,kdc}.{crt,key}: pkinit certificates + + * data/gen-req.sh: Generate pkinit certificates. + + * data/openssl.cnf: Add pkinit glue. + + * cert.c (hx509_verify_hostname): implement stub function + +2006-04-27 Love Hörnquist Åstrand <lha@it.su.se> + + * TODO: CRL delta support + +2006-04-26 Love Hörnquist Åstrand <lha@it.su.se> + + * data/.cvsignore: ignore leftover from OpenSSL cert generation + + * hx509_err.et: Add name malformated error + + * name.c (hx509_parse_name): don't abort on error, rather return + error + + * test_name.c: Test failure parsing name. + + * cert.c: When verifying certificates, store subject basename for + later consumption. + + * test_name.c: test to parse and print name and check that they + are the same. + + * name.c (hx509_parse_name): fix length argument to printf string + + * name.c (hx509_parse_name): fix length argument to stringtooid, 1 + too short. + + * cert.c: remove debug printf's + + * name.c (hx509_parse_name): make compile pre c99 + + * data/gen-req.sh: OpenSSL have a serious issue of user confusion + -subj in -ca takes the arguments in LDAP order. -subj for x509 + takes it in x509 order. + + * cert.c (hx509_verify_path): handle the case where the where two + proxy certs in a chain. + + * test_chain.in: enable two proxy certificates in a chain test + + * test_chain.in: tests proxy certificates + + * data: re-gen + + * data/gen-req.sh: build proxy certificates + + * data/openssl.cnf: add def for proxy10_cert + + * hx509_err.et: Add another proxy certificate error. + + * cert.c (hx509_verify_path): Need to mangle name to remove the CN + of the subject, copying issuer only works for one level but is + better then doing no checking at all. + + * hxtool.c: Add verify --allow-proxy-certificate. + + * hxtool-commands.in: add verify --allow-proxy-certificate + + * hx509_err.et: Add proxy certificate errors. + + * cert.c: Fix comment about subject name of proxy certificate. + + * test_chain.in: tests for proxy certs + + * data/gen-req.sh: gen proxy and non-proxy tests certificates + + * data/openssl.cnf: Add definition for proxy certs + + * data/*proxy-test.*: Add proxy certificates + + * cert.c (hx509_verify_path): verify proxy certificate have no san + or ian + + * cert.c (hx509_verify_set_proxy_certificate): Add + (*): rename policy cert to proxy cert + + * cert.c: Initial support for proxy certificates. + +2006-04-24 Love Hörnquist Åstrand <lha@it.su.se> + + * hxtool.c: some error checking + + * name.c: Switch over to asn1 generaed oids. + + * TODO: merge with old todo file + +2006-04-23 Love Hörnquist Åstrand <lha@it.su.se> + + * test_query.in: make quiet + + * test_req.in: SKIP test if there is no RSA support. + + * hxtool.c: print dh method too + + * test_chain.in: SKIP test if there is no RSA support. + + * test_cms.in: SKIP test if there is no RSA support. + + * test_nist.in: SKIP test if there is no RSA support. + +2006-04-22 Love Hörnquist Åstrand <lha@it.su.se> + + * hxtool-commands.in: Allow passing in pool and anchor to + signedData + + * hxtool.c: Allow passing in pool and anchor to signedData + + * test_cms.in: Test that certs in signed data is picked up. + + * hx_locl.h: Expose the path building function to internal + functions. + + * cert.c: Expose the path building function to internal functions. + + * hxtool-commands.in: cms-envelope: Add support for choosing the + encryption type + + * hxtool.c (cms_create_enveloped): Add support for choosing the + encryption type + + * test_cms.in: Test generating des-ede3 aes-128 aes-256 enveloped + data + + * crypto.c: Add names to cipher types. + + * cert.c (hx509_query_match_friendly_name): fix return value + + * data/gen-req.sh: generate tests for enveloped data using + des-ede3 and aes256 + + * test_cms.in: add tests for enveloped data using des-ede3 and + aes256 + + * cert.c (hx509_query_match_friendly_name): New function. + +2006-04-21 Love Hörnquist Åstrand <lha@it.su.se> + + * ks_p11.c: Add support for parsing slot-number. + + * crypto.c (oid_private_rc2_40): simply + + * crypto.c: Use oids from asn1 generator. + + * ks_file.c (file_init): reset length when done with a part + + * test_cms.in: check with test.combined.crt. + + * data/gen-req.sh: Create test.combined.crt. + + * test_cms.in: Test signed data using keyfile that is encrypted. + + * ks_file.c: Remove (commented out) debug printf + + * ks_file.c (parse_rsa_private_key): use EVP_get_cipherbyname + + * ks_file.c (parse_rsa_private_key): make working for one + password. + + * ks_file.c (parse_rsa_private_key): Implement enought for + testing. + + * hx_locl.h: Add <ctype.h> + + * ks_file.c: Add glue code for PEM encrypted password files. + + * test_cms.in: Add commeted out password protected PEM file, + remove password for those tests that doesn't need it. + + * test_cms.in: adapt test now that we can use any certificate and + trust anchor + + * collector.c: handle PEM RSA PRIVATE KEY files + + * cert.c: Remove unused function. + + * ks_dir.c: move code here from ks_file.c now that its no longer + used. + + * ks_file.c: Add support for parsing unencrypted RSA PRIVATE KEY + + * crypto.c: Handle rsa private keys better. + +2006-04-20 Love Hörnquist Åstrand <lha@it.su.se> + + * hxtool.c: Use hx509_cms_{,un}wrap_ContentInfo + + * cms.c: Make hx509_cms_{,un}wrap_ContentInfo usable in asn1 + un-aware code. + + * cert.c (hx509_verify_path): if trust anchor is not self signed, + don't check sig From Douglas Engert. + + * test_chain.in: test "sub-cert -> sub-ca" + + * crypto.c: Use the right length for the sha256 checksums. + +2006-04-15 Love Hörnquist Åstrand <lha@it.su.se> + + * crypto.c: Fix breakage from sha256 code. + + * crypto.c: Add SHA256 support, and symbols for the other new + SHA-2 types. + +2006-04-14 Love Hörnquist Åstrand <lha@it.su.se> + + * test_cms.in: test rc2-40 rc2-64 rc2-128 enveloped data + + * data/test-enveloped-rc2-{40,64,128}: add tests cases for rc2 + + * cms.c: Update prototypes changes for hx509_crypto_[gs]et_params. + + * crypto.c: Break out the parameter handling code for encrypting + data to handle RC2. Needed for Windows 2k pk-init support. + +2006-04-04 Love Hörnquist Åstrand <lha@it.su.se> + + * Makefile.am: Split libhx509_la_SOURCES into build file and + distributed files so we can avoid building prototypes for + build-files. + +2006-04-03 Love Hörnquist Åstrand <lha@it.su.se> + + * TODO: split certificate request into pkcs10 and CRMF + + * hxtool-commands.in: Add nonce flag to ocsp-fetch + + * hxtool.c: control sending nonce + + * hxtool.c (request_create): store the request in a file, no in + bitbucket. + + * cert.c: expose print_cert_subject internally + + * hxtool.c: Add ocsp_print. + + * hxtool-commands.in: New command "ocsp-print". + + * hx_locl.h: Include <hex.h>. + + * revoke.c (verify_ocsp): require issuer to match too. + (free_ocsp): new function + (hx509_revoke_ocsp_print): new function, print ocsp reply + + * Makefile.am: build CRMF files + + * data/key.der: needed for cert request test + + * test_req.in: adapt to rename of pkcs10-create to request-create + + * hxtool.c: adapt to rename of pkcs10-create to request-create + + * hxtool-commands.in: Rename pkcs10-create to request-create + + * crypto.c: (_hx509_parse_private_key): Avoid crashing on bad input. + + * hxtool.c (pkcs10_create): use opt->subject_string + + * hxtool-commands.in: Add pkcs10-create --subject + + * Makefile.am: Add test_req to tests. + + * test_req.in: Test for pkcs10 commands. + + * name.c (hx509_parse_name): new function. + + * hxtool.c (pkcs10_create): implement + + * hxtool-commands.in (pkcs10-create): Add arguments + + * crypto.c: Add _hx509_private_key2SPKI and support + functions (only support RSA for now). + +2006-04-02 Love Hörnquist Åstrand <lha@it.su.se> + + * hxtool-commands.in: Add pkcs10-create command. + + * hx509.h: Add hx509_request. + + * TODO: more stuff + + * Makefile.am: Add req.c + + * req.c: Create certificate requests, prototype converts the + request in a pkcs10 packet. + + * hxtool.c: Add pkcs10_create + + * name.c (hx509_name_copy): new function. + +2006-04-01 Love Hörnquist Åstrand <lha@it.su.se> + + * TODO: fill out what do + + * hxtool-commands.in: add pkcs10-print + + * hx_locl.h: Include <pkcs10_asn1.h>. + + * pkcs10.asn1: PKCS#10 + + * hxtool.c (pkcs10_print): new function. + + * test_chain.in: test ocsp keyhash + + * data: generate ocsp keyhash version too + + * revoke.c (load_ocsp): test that we got back a BasicReponse + + * ocsp.asn1: Add asn1_id_pkix_ocsp*. + + * Makefile.am: Add asn1_id_pkix_ocsp*. + + * cert.c: Add HX509_QUERY_MATCH_KEY_HASH_SHA1 + + * hx_locl.h: Add HX509_QUERY_MATCH_KEY_HASH_SHA1 + + * revoke.c: Support OCSPResponderID.byKey, indent. + + * revoke.c (hx509_ocsp_request): Add nonce to ocsp request. + + * hxtool.c: Add nonce to ocsp request. + + * test_chain.in: Added crl tests + + * data/nist-data: rename missing-crl to missing-revoke + + * data: make ca use openssl ca command so we can add ocsp tests, + and regen certs + + * test_chain.in: Add revoked ocsp cert test + + * cert.c: rename missing-crl to missing-revoke + + * revoke.c: refactor code, fix a un-init-ed variable + + * test_chain.in: rename missing-crl to missing-revoke add ocsp + tests + + * test_cms.in: rename missing-crl to missing-revoke + + * hxtool.c: rename missing-crl to missing-revoke + + * hxtool-commands.in: rename missing-crl to missing-revoke + + * revoke.c: Plug one memory leak. + + * revoke.c: Renamed generic CRL related errors. + + * hx509_err.et: Comments and renamed generic CRL related errors + + * revoke.c: Add ocsp checker. + + * ocsp.asn1: Add id-kp-OCSPSigning + + * hxtool-commands.in: add url-path argument to ocsp-fetch + + * hxtool.c: implement ocsp-fetch + + * cert.c: Use HX509_DEFAULT_OCSP_TIME_DIFF. + + * hx_locl.h: Add ocsp_time_diff to hx509_context + + * crypto.c (_hx509_verify_signature_bitstring): new function, + commonly use when checking certificates + + * cms.c (hx509_cms_envelope_1): check for internal ASN.1 encoder + error + + * cert.c: Add ocsp glue, use new + _hx509_verify_signature_bitstring, add eku checking function. + +2006-03-31 Love Hörnquist Åstrand <lha@it.su.se> + + * Makefile.am: add id_kp_OCSPSigning.x + + * revoke.c: Pick out certs in ocsp response + + * TODO: list of stuff to verify + + * revoke.c: Add code to load OCSPBasicOCSPResponse files, reload + crl when its changed on disk. + + * cert.c: Update for ocsp merge. handle building path w/o + subject (using subject key id) + + * ks_p12.c: _hx509_map_file changed prototype. + + * file.c: _hx509_map_file changed prototype, returns struct stat + if requested. + + * ks_file.c: _hx509_map_file changed prototype. + + * hxtool.c: Add stub for ocsp-fetch, _hx509_map_file changed + prototype, add ocsp parsing to verify command. + + * hx_locl.h: rename HX509_CTX_CRL_MISSING_OK to + HX509_CTX_VERIFY_MISSING_OK now that we have OCSP glue + +2006-03-30 Love Hörnquist Åstrand <lha@it.su.se> + + * hx_locl.h: Add <krb5-types.h> to make it compile on Solaris, + from Alex V. Labuta. + +2006-03-28 Love Hörnquist Åstrand <lha@it.su.se> + + * crypto.c (_hx509_pbe_decrypt): try all passwords, not just the + first one. + +2006-03-27 Love Hörnquist Åstrand <lha@it.su.se> + + * print.c (check_altName): Print the othername oid. + + * crypto.c: Manual page claims RSA_public_decrypt will return -1 + on error, lets check for that + + * crypto.c (_hx509_pbe_decrypt): also try the empty password + + * collector.c (match_localkeyid): no need to add back the cert to + the cert pool, its already there. + + * crypto.c: Add REQUIRE_SIGNER + + * cert.c (hx509_cert_free): ok to free NULL + + * hx509_err.et: Add new error code SIGNATURE_WITHOUT_SIGNER. + + * name.c (_hx509_name_ds_cmp): make DirectoryString case + insenstive + (hx509_name_to_string): less spacing + + * cms.c: Check for signature error, check consitency of error + +2006-03-26 Love Hörnquist Åstrand <lha@it.su.se> + + * collector.c (_hx509_collector_alloc): handle errors + + * cert.c (hx509_query_alloc): allocate slight more more then a + sizeof(pointer) + + * crypto.c (_hx509_private_key_assign_key_file): ask for password + if nothing matches. + + * cert.c: Expose more of the hx509_query interface. + + * collector.c: hx509_certs_find is now exposed. + + * cms.c: hx509_certs_find is now exposed. + + * revoke.c: hx509_certs_find is now exposed. + + * keyset.c (hx509_certs_free): allow free-ing NULL + (hx509_certs_find): expose + (hx509_get_one_cert): new function + + * hxtool.c: hx509_certs_find is now exposed. + + * hx_locl.h: Remove hx509_query, its exposed now. + + * hx509.h: Add hx509_query. + +2006-02-22 Love Hörnquist Åstrand <lha@it.su.se> + + * cert.c: Add exceptions for null (empty) subjectNames + + * data/nist-data: Add some more name constraints tests. + + * data/nist-data: Add some of the test from 4.13 Name Constraints. + + * cert.c: Name constraits needs to be evaluated in block as they + appear in the certificates, they can not be joined to one + list. One example of this is: + + - cert is cn=foo,dc=bar,dc=baz + - subca is dc=foo,dc=baz with name restriction dc=kaka,dc=baz + - ca is dc=baz with name restriction dc=baz + + If the name restrictions are merged to a list, the certificate + will pass this test. + +2006-02-14 Love Hörnquist Åstrand <lha@it.su.se> + + * cert.c: Handle more name constraints cases. + + * crypto.c (dsa_verify_signature): if test if malloc failed + +2006-01-31 Love Hörnquist Åstrand <lha@it.su.se> + + * cms.c: Drop partial pkcs12 string2key implementation. + +2006-01-20 Love Hörnquist Åstrand <lha@it.su.se> + + * data/nist-data: Add commited out DSA tests (they fail). + + * data/nist-data: Add 4.2 Validity Periods. + + * test_nist.in: Make less verbose to use. + + * Makefile.am: Add test_nist_cert. + + * data/nist-data: Add some more CRL-tests. + + * test_nist.in: Print $id instead of . when running the tests. + + * test_nist.in: Drop verifying certifiates, its done in another + test now. + + * data/nist-data: fixup kill-rectangle leftovers + + * data/nist-data: Drop verifying certifiates, its done in another + test now. Add more crl tests. comment out all unused tests. + + * test_nist_cert.in: test parse all nist certs + +2006-01-19 Love Hörnquist Åstrand <lha@it.su.se> + + * hx509_err.et: Add HX509_CRL_UNKNOWN_EXTENSION. + + * revoke.c: Check for unknown extentions in CRLs and CRLEntries. + + * test_nist.in: Parse new format to handle CRL info. + + * test_chain.in: Add --missing-crl. + + * name.c (hx509_unparse_der_name): Rename from hx509_parse_name. + (_hx509_unparse_Name): Add. + + * hxtool-commands.in: Add --missing-crl to verify commands. + + * hx509_err.et: Add CRL errors. + + * cert.c (hx509_context_set_missing_crl): new function Add CRL + handling. + + * hx_locl.h: Add HX509_CTX_CRL_MISSING_OK. + + * revoke.c: Parse and verify CRLs (simplistic). + + * hxtool.c: Parse CRL info. + + * data/nist-data: Change format so we can deal with CRLs, also + note the test-id from PKITS. + + * data: regenerate test + + * data/gen-req.sh: use static-file to generate tests + + * data/static-file: new file to use for commited tests + + * test_cms.in: Use static file, add --missing-crl. + +2006-01-18 Love Hörnquist Åstrand <lha@it.su.se> + + * print.c: Its cRLReason, not cRLReasons. + + * hxtool.c: Attach revoke context to verify context. + + * data/nist-data: change syntax to make match better with crl + checks + + * cert.c: Verify no certificates has been revoked with the new + revoke interface. + + * Makefile.am: libhx509_la_SOURCES += revoke.c + + * revoke.c: Add framework for handling CRLs. + + * hx509.h: Add hx509_revoke_ctx. + +2006-01-13 Love Hörnquist Åstrand <lha@it.su.se> + + * delete crypto_headers.h, use global file instead. + + * crypto.c (PBE_string2key): libdes now supports PKCS12_key_gen + +2006-01-12 Love Hörnquist Åstrand <lha@it.su.se> + + * crypto_headers.h: Need BN_is_negative too. + +2006-01-11 Love Hörnquist Åstrand <lha@it.su.se> + + * ks_p11.c (p11_rsa_public_decrypt): since is wrong, don't provide + it. PKCS11 can't do public_decrypt, it support verify though. All + this doesn't matter, since the code never go though this path. + + * crypto_headers.h: Provide glue to compile with less warnings + with OpenSSL + +2006-01-08 Love Hörnquist Åstrand <lha@it.su.se> + + * Makefile.am: Depend on LIB_des + + * lock.c: Use "crypto_headers.h". + + * crypto_headers.h: Include the two diffrent implementation of + crypto headers. + + * cert.c: Use "crypto-headers.h". Load ENGINE configuration. + + * crypto.c: Make compile with both OpenSSL and heimdal libdes. + + * ks_p11.c: Add code for public key decryption (not supported yet) + and use "crypto-headers.h". + + +2006-01-04 Love Hörnquist Åstrand <lha@it.su.se> + + * add a hx509_context where we can store configuration + + * p11.c,Makefile.am: pkcs11 is now supported by library, remove + old files. + + * ks_p11.c: more paranoid on refcount, set refcounter ealier, + reset pointers after free + + * collector.c (struct private_key): remove temporary key data + storage, convert directly to a key + (match_localkeyid): match certificate and key using localkeyid + (match_keys): match certificate and key using _hx509_match_keys + (_hx509_collector_collect): rewrite to use match_keys and + match_localkeyid + + * crypto.c (_hx509_match_keys): function that determins if a + private key matches a certificate, used when there is no + localkeyid. + (*) reset free pointer + + * ks_file.c: Rewrite to use collector and mapping support + function. + + * ks_p11.c (rsa_pkcs1_method): constify + + * ks_p11.c: drop extra wrapping of p11_init + + * crypto.c (_hx509_private_key_assign_key_file): use function to + extact rsa key + + * cert.c: Revert previous, refcounter is unsigned, so it can never + be negative. + + * cert.c (hx509_cert_ref): more refcount paranoia + + * ks_p11.c: Implement rsa_private_decrypt and add stubs for public + ditto. + + * ks_p11.c: Less printf, less memory leaks. + + * ks_p11.c: Implement signing using pkcs11. + + * ks_p11.c: Partly assign private key, enough to complete + collection, but not any crypto functionallity. + + * collector.c: Use hx509_private_key to assign private keys. + + * crypto.c: Remove most of the EVP_PKEY code, and use RSA + directly, this temporary removes DSA support. + + * hxtool.c (print_f): print if there is a friendly name and if + there is a private key + +2006-01-03 Love Hörnquist Åstrand <lha@it.su.se> + + * name.c: Avoid warning from missing __attribute__((noreturn)) + + * lock.c (_hx509_lock_unlock_certs): return unlock certificates + + * crypto.c (_hx509_private_key_assign_ptr): new function, exposes + EVP_PKEY + (_hx509_private_key_assign_key_file): remember to free private key + if there is one. + + * cert.c (_hx509_abort): add newline to output and flush stdout + + * Makefile.am: libhx509_la_SOURCES += collector.c + + * hx_locl.h: forward type declaration of struct hx509_collector. + + * collector.c: Support functions to collect certificates and + private keys and then match them. + + * ks_p12.c: Use the new hx509_collector support functions. + + * ks_p11.c: Add enough glue to support certificate iteration. + + * test_nist_pkcs12.in: Less verbose. + + * cert.c (hx509_cert_free): if there is a private key assosited + with this cert, free it + + * print.c: Use _hx509_abort. + + * ks_p12.c: Use _hx509_abort. + + * hxtool.c: Use _hx509_abort. + + * crypto.c: Use _hx509_abort. + + * cms.c: Use _hx509_abort. + + * cert.c: Use _hx509_abort. + + * name.c: use _hx509_abort + +2006-01-02 Love Hörnquist Åstrand <lha@it.su.se> + + * name.c (hx509_name_to_string): don't cut bmpString in half. + + * name.c (hx509_name_to_string): don't overwrite with 1 byte with + bmpString. + + * ks_file.c (parse_certificate): avoid stomping before array + + * name.c (oidtostring): avoid leaking memory + + * keyset.c: Add _hx509_ks_dir_register. + + * Makefile.am (libhx509_la_SOURCES): += ks_dir.c + + * hxtool-commands.in: Remove pkcs11. + + * hxtool.c: Remove pcert_pkcs11. + + * ks_file.c: Factor out certificate parsing code. + + * ks_dir.c: Add new keystore that treats all files in a directory + a keystore, useful for regression tests. + +2005-12-12 Love Hörnquist Åstrand <lha@it.su.se> + + * test_nist_pkcs12.in: Test parse PKCS12 files from NIST. + + * data/nist-data: Can handle DSA certificate. + + * hxtool.c: Print error code on failure. + +2005-10-29 Love Hörnquist Åstrand <lha@it.su.se> + + * crypto.c: Support DSA signature operations. + +2005-10-04 Love Hörnquist Åstrand <lha@it.su.se> + + * print.c: Validate that issuerAltName and subjectAltName isn't + empty. + +2005-09-14 Love Hörnquist Åstrand <lha@it.su.se> + + * p11.c: Cast to unsigned char to avoid warning. + + * keyset.c: Register pkcs11 module. + + * Makefile.am: Add ks_p11.c, install hxtool. + + * ks_p11.c: Starting point of a pkcs11 module. + +2005-09-04 Love Hörnquist Åstrand <lha@it.su.se> + + * lock.c: Implement prompter. + + * hxtool-commands.in: add --content to print + + * hxtool.c: Split verify and print. + + * cms.c: _hx509_pbe_decrypt now takes a hx509_lock. + + * crypto.c: Make _hx509_pbe_decrypt take a hx509_lock, workaround + for empty password. + + * name.c: Add DC, handle all Directory strings, fix signless + problems. + +2005-09-03 Love Hörnquist Åstrand <lha@it.su.se> + + * test_query.in: Pass in --pass to all commands. + + * hxtool.c: Use option --pass. + + * hxtool-commands.in: Add --pass to all commands. + + * hx509_err.et: add UNKNOWN_LOCK_COMMAND and CRYPTO_NO_PROMPTER + + * test_cms.in: pass in password to cms-create-sd + + * crypto.c: Abstract out PBE_string2key so I can add PBE2 s2k + later. Avoid signess warnings with OpenSSL. + + * cms.c: Use void * instead of char * for to avoid signedness + issues + + * cert.c (hx509_cert_get_attribute): remove const, its not + + * ks_p12.c: Cast size_t to unsigned long when print. + + * name.c: Fix signedness warning. + + * test_query.in: Use echo, the function check isn't defined here. + +2005-08-11 Love Hörnquist Åstrand <lha@it.su.se> + + * hxtool-commands.in: Add more options that was missing. + +2005-07-28 Love Hörnquist Åstrand <lha@it.su.se> + + * test_cms.in: Use --certificate= for enveloped/unenvelope. + + * hxtool.c: Use --certificate= for enveloped/unenvelope. Clean + up. + + * test_cms.in: add EnvelopeData tests + + * hxtool.c: use id-envelopedData for ContentInfo + + * hxtool-commands.in: add contentinfo wrapping for create/unwrap + enveloped data + + * hxtool.c: add contentinfo wrapping for create/unwrap enveloped + data + + * data/gen-req.sh: add enveloped data (aes128) + + * crypto.c: add "new" RC2 oid + +2005-07-27 Love Hörnquist Åstrand <lha@it.su.se> + + * hx_locl.h, cert.c: Add HX509_QUERY_MATCH_FUNCTION that allows + caller to match by function, note that this doesn't not work + directly for backends that implements ->query, they must do their + own processing. (I'm running out of flags, only 12 left now) + + * test_cms.in: verify ContentInfo wrapping code in hxtool + + * hxtool-commands.in (cms_create_sd): support wrapping in content + info spelling + + * hxtool.c (cms_create_sd): support wrapping in content info + + * test_cms.in: test more cms signeddata messages + + * data/gen-req.sh: generate SignedData + + * hxtool.c (cms_create_sd): support certificate store, add support + to unwrap a ContentInfo the SignedData inside. + + * crypto.c: sprinkel rk_UNCONST + + * crypto.c: add DER NULL to the digest oid's + + * hxtool-commands.in: add --content-info to cms-verify-sd + + * cms.c (hx509_cms_create_signed_1): pass in a full + AlgorithmIdentifier instead of heim_oid for digest_alg + + * crypto.c: make digest_alg a digest_oid, it's not needed right + now + + * hx509_err.et: add CERT_NOT_FOUND + + * keyset.c (_hx509_certs_find): add error code for cert not + found + + * cms.c (hx509_cms_verify_signed): add external store of + certificates, use the right digest algorithm identifier. + + * cert.c: fix const warning + + * ks_p12.c: slightly less verbose + + * cert.c: add hx509_cert_find_subjectAltName_otherName, add + HX509_QUERY_MATCH_FRIENDLY_NAME + + * hx509.h: add hx509_octet_string_list, remove bad comment + + * hx_locl.h: add HX509_QUERY_MATCH_FRIENDLY_NAME + + * keyset.c (hx509_certs_append): needs a hx509_lock, add one + + * Makefile.am: add test cases tempfiles to CLEANFILES + + * Makefile.am: add test_query to TESTS, fix dependency on hxtool + sources on hxtool-commands.h + + * hxtool-commands.in: explain what signer is for create-sd + + * hxtool.c: add query, add more options to verify-sd and create-sd + + * test_cms.in: add more cms tests + + * hxtool-commands.in: add query, add more options to verify-sd + + * test_query.in: test query interface + + * data: fix filenames for ds/ke files, add pkcs12 files, regen + + * hxtool.c,Makefile.am,hxtool-commands.in: switch to slc + +2005-07-26 Love Hörnquist Åstrand <lha@it.su.se> + + * cert.c (hx509_verify_destroy_ctx): add + + * hxtool.c: free hx509_verify_ctx + + * name.c (_hx509_name_ds_cmp): make sure all strings are not equal + +2005-07-25 Love Hörnquist Åstrand <lha@it.su.se> + + * hxtool.c: return error + + * keyset.c: return errors from iterations + + * test_chain.in: clean up checks + + * ks_file.c (parse_certificate): return errno's not 1 in case of + error + + * ks_file.c (file_iter): make sure endpointer is NULL + + * ks_mem.c (mem_iter): follow conversion and return NULL when we + get to the end, not ENOENT. + + * Makefile.am: test_chain depends on hxtool + + * data: test certs that lasts 10 years + + * data/gen-req.sh: script to generate test certs + + * Makefile.am: Add regression tests. + + * data: test certificate and keys + + * test_chain.in: test chain + + * hxtool.c (cms_create_sd): add KU digitalSigature as a + requirement to the query + + * hx_locl.h: add KeyUsage query bits + + * hx509_err.et: add KeyUsage error + + * cms.c: add checks for KeyUsage + + * cert.c: more checks on KeyUsage, allow to query on them too + +2005-07-24 Love Hörnquist Åstrand <lha@it.su.se> + + * cms.c: Add missing break. + + * hx_locl.h,cms.c,cert.c: allow matching on SubjectKeyId + + * hxtool.c: Use _hx509_map_file, _hx509_unmap_file and + _hx509_write_file. + + * file.c (_hx509_write_file): in case of write error, return errno + + * file.c (_hx509_write_file): add a function that write a data + blob to disk too + + * Fix id-tags + + * Import mostly complete X.509 and CMS library. Handles, PEM, DER, + PKCS12 encoded certicates. Verificate RSA chains and handled + CMS's SignedData, and EnvelopedData. + + diff --git a/third_party/heimdal/lib/hx509/Makefile.am b/third_party/heimdal/lib/hx509/Makefile.am new file mode 100644 index 0000000..214dabf --- /dev/null +++ b/third_party/heimdal/lib/hx509/Makefile.am @@ -0,0 +1,398 @@ +include $(top_srcdir)/Makefile.am.common + +AM_CPPFLAGS += $(INCLUDE_openssl_crypto) + +lib_LTLIBRARIES = libhx509.la libhx509template.la +libhx509_la_LDFLAGS = -version-info 5:0:0 +libhx509template_la_LDFLAGS = -version-info 5:0:0 + +BUILT_SOURCES = \ + sel-gram.h \ + hx509_err.c \ + hx509_err.h + +AM_YFLAGS = -o sel-gram.c + +dist_libhx509_la_SOURCES = \ + ca.c \ + cert.c \ + char_map.h \ + cms.c \ + collector.c \ + crypto.c \ + crypto-ec.c \ + doxygen.c \ + error.c \ + env.c \ + file.c \ + hx509.h \ + hx_locl.h \ + sel.c \ + sel.h \ + sel-gram.y \ + sel-lex.l \ + keyset.c \ + ks_dir.c \ + ks_file.c \ + ks_mem.c \ + ks_null.c \ + ks_p11.c \ + ks_p12.c \ + ks_keychain.c \ + lock.c \ + name.c \ + peer.c \ + print.c \ + softp11.c \ + ref/pkcs11.h \ + req.c \ + revoke.c + +dist_libhx509template_la_SOURCES = $(dist_libhx509_la_SOURCES) + +sel-gram.h: sel-gram.c +sel-lex.c: sel-gram.h + +libhx509_la_DEPENDENCIES = version-script.map +libhx509template_la_DEPENDENCIES = version-script.map + +libhx509_la_LIBADD = \ + $(LIB_com_err) \ + $(LIB_hcrypto) \ + $(LIB_openssl_crypto) \ + $(top_builddir)/lib/asn1/libasn1.la \ + $(top_builddir)/lib/wind/libwind.la \ + $(top_builddir)/lib/base/libheimbase.la \ + $(LIBADD_roken) \ + $(LIB_dlopen) + +libhx509template_la_LIBADD = \ + $(LIB_com_err) \ + $(LIB_hcrypto) \ + $(LIB_openssl_crypto) \ + $(top_builddir)/lib/asn1/libasn1template.la \ + $(top_builddir)/lib/wind/libwind.la \ + $(top_builddir)/lib/base/libheimbase.la \ + $(LIBADD_roken) \ + $(LIB_dlopen) + +if FRAMEWORK_SECURITY +libhx509_la_LDFLAGS += -framework Security -framework CoreFoundation +libhx509template_la_LDFLAGS += -framework Security -framework CoreFoundation +endif + +if versionscript +libhx509_la_LDFLAGS += $(LDFLAGS_VERSION_SCRIPT)$(srcdir)/version-script.map +libhx509template_la_LDFLAGS += $(LDFLAGS_VERSION_SCRIPT)$(srcdir)/version-script.map +endif +$(libhx509_la_OBJECTS): $(srcdir)/version-script.map $(nodist_include_HEADERS) $(priv_headers) +$(libhx509template_la_OBJECTS): $(srcdir)/version-script.map $(nodist_include_HEADERS) $(priv_headers) + +nodist_libhx509_la_SOURCES = $(BUILT_SOURCES) +nodist_libhx509template_la_SOURCES = $(BUILT_SOURCES) + +dist_include_HEADERS = hx509.h $(srcdir)/hx509-protos.h + +noinst_HEADERS = $(srcdir)/hx509-private.h + +nodist_include_HEADERS = hx509_err.h + +ALL_OBJECTS = $(libhx509_la_OBJECTS) +ALL_OBJECTS += $(hxtool_OBJECTS) + +HX509_PROTOS = $(srcdir)/hx509-protos.h $(srcdir)/hx509-private.h + +$(ALL_OBJECTS): $(HX509_PROTOS) + +$(libhx509_la_OBJECTS): $(srcdir)/hx_locl.h +$(libhx509template_la_OBJECTS): $(srcdir)/hx_locl.h + +$(srcdir)/hx509-protos.h: $(dist_libhx509_la_SOURCES) + $(heim_verbose)cd $(srcdir) && perl ../../cf/make-proto.pl -R '^(_|^C)' -E HX509_LIB -q -P comment -o hx509-protos.h $(dist_libhx509_la_SOURCES) || rm -f hx509-protos.h + +$(srcdir)/hx509-private.h: $(dist_libhx509_la_SOURCES) + $(heim_verbose)cd $(srcdir) && perl ../../cf/make-proto.pl -q -P comment -p hx509-private.h $(dist_libhx509_la_SOURCES) || rm -f hx509-private.h + +bin_PROGRAMS = hxtool + +hxtool-commands.c hxtool-commands.h: hxtool-commands.in $(SLC) + $(heim_verbose)$(SLC) $(srcdir)/hxtool-commands.in + +dist_hxtool_SOURCES = hxtool.c +nodist_hxtool_SOURCES = hxtool-commands.c hxtool-commands.h + +$(hxtool_OBJECTS): hxtool-commands.h $(nodist_include_HEADERS) + +hxtool_LDADD = \ + libhx509template.la \ + $(top_builddir)/lib/asn1/libasn1.la \ + $(LIB_hcrypto) \ + $(LIB_roken) \ + $(top_builddir)/lib/sl/libsl.la + +CLEANFILES = $(BUILT_SOURCES) sel-gram.c sel-lex.c \ + $(TESTS) \ + hxtool-commands.c hxtool-commands.h *.tmp \ + request.out \ + out.pem out2.pem \ + sd sd.pem \ + sd.data sd.data.out \ + ev.data ev.data.out \ + cert-null.pem cert-sub-ca2.pem \ + cert-ee.pem cert-ca.pem \ + cert-sub-ee.pem cert-sub-ca.pem \ + cert-proxy.der cert-ca.der cert-ee.der pkcs10-request.der \ + wca.pem wuser.pem wdc.pem wcrl.crl \ + random-data statfile crl.crl \ + test p11dbg.log pkcs11.cfg \ + test-rc-file.rc + +clean-local: + @echo "cleaning PKITS" ; rm -rf PKITS_data + +# +# regression tests +# + +check_SCRIPTS = $(SCRIPT_TESTS) +check_PROGRAMS = $(PROGRAM_TESTS) test_soft_pkcs11 + +LDADD = libhx509.la + +test_soft_pkcs11_LDADD = libhx509.la $(top_builddir)/lib/asn1/libasn1.la + +test_name_LDADD = libhx509.la $(LIB_roken) $(top_builddir)/lib/asn1/libasn1.la +test_expr_LDADD = libhx509.la $(LIB_roken) $(top_builddir)/lib/asn1/libasn1.la + +TESTS = $(SCRIPT_TESTS) $(PROGRAM_TESTS) + +PROGRAM_TESTS = \ + test_name \ + test_expr + +SCRIPT_TESTS = \ + test_ca \ + test_cert \ + test_chain \ + test_cms \ + test_crypto \ + test_nist \ + test_nist2 \ + test_pkcs11 \ + test_java_pkcs11 \ + test_nist_cert \ + test_nist_pkcs12 \ + test_req \ + test_windows \ + test_query + +do_subst = $(heim_verbose)sed -e 's,[@]srcdir[@],$(srcdir),g' \ + -e 's,[@]objdir[@],$(top_builddir)/lib/hx509,g' \ + -e 's,[@]egrep[@],$(EGREP),g' + +test_ca: test_ca.in Makefile + $(do_subst) < $(srcdir)/test_ca.in > test_ca.tmp + $(heim_verbose)chmod +x test_ca.tmp + mv test_ca.tmp test_ca + +test_cert: test_cert.in Makefile + $(do_subst) < $(srcdir)/test_cert.in > test_cert.tmp + $(heim_verbose)chmod +x test_cert.tmp + mv test_cert.tmp test_cert + +test_chain: test_chain.in Makefile + $(do_subst) < $(srcdir)/test_chain.in > test_chain.tmp + $(heim_verbose)chmod +x test_chain.tmp + mv test_chain.tmp test_chain + +test_cms: test_cms.in Makefile + $(do_subst) < $(srcdir)/test_cms.in > test_cms.tmp + $(heim_verbose)chmod +x test_cms.tmp + mv test_cms.tmp test_cms + +test_crypto: test_crypto.in Makefile + $(do_subst) < $(srcdir)/test_crypto.in > test_crypto.tmp + $(heim_verbose)chmod +x test_crypto.tmp + mv test_crypto.tmp test_crypto + +test_nist: test_nist.in Makefile + $(do_subst) < $(srcdir)/test_nist.in > test_nist.tmp + $(heim_verbose)chmod +x test_nist.tmp + mv test_nist.tmp test_nist + +test_nist2: test_nist2.in Makefile + $(do_subst) < $(srcdir)/test_nist2.in > test_nist2.tmp + $(heim_verbose)chmod +x test_nist2.tmp + mv test_nist2.tmp test_nist2 + +test_pkcs11: test_pkcs11.in Makefile + $(do_subst) < $(srcdir)/test_pkcs11.in > test_pkcs11.tmp + $(heim_verbose)chmod +x test_pkcs11.tmp + mv test_pkcs11.tmp test_pkcs11 + +test_java_pkcs11: test_java_pkcs11.in Makefile + $(do_subst) < $(srcdir)/test_java_pkcs11.in > test_java_pkcs11.tmp + $(heim_verbose)chmod +x test_java_pkcs11.tmp + mv test_java_pkcs11.tmp test_java_pkcs11 + +test_nist_cert: test_nist_cert.in Makefile + $(do_subst) < $(srcdir)/test_nist_cert.in > test_nist_cert.tmp + $(heim_verbose)chmod +x test_nist_cert.tmp + mv test_nist_cert.tmp test_nist_cert + +test_nist_pkcs12: test_nist_pkcs12.in Makefile + $(do_subst) < $(srcdir)/test_nist_pkcs12.in > test_nist_pkcs12.tmp + $(heim_verbose)chmod +x test_nist_pkcs12.tmp + mv test_nist_pkcs12.tmp test_nist_pkcs12 + +test_req: test_req.in Makefile + $(do_subst) < $(srcdir)/test_req.in > test_req.tmp + $(heim_verbose)chmod +x test_req.tmp + mv test_req.tmp test_req + +test_windows: test_windows.in Makefile + $(do_subst) < $(srcdir)/test_windows.in > test_windows.tmp + $(heim_verbose)chmod +x test_windows.tmp + mv test_windows.tmp test_windows + +test_query: test_query.in Makefile + $(do_subst) < $(srcdir)/test_query.in > test_query.tmp + $(heim_verbose)chmod +x test_query.tmp + mv test_query.tmp test_query + +EXTRA_DIST = \ + NTMakefile \ + hxtool-version.rc \ + libhx509-exports.def \ + version-script.map \ + hx509_err.et \ + hxtool-commands.in \ + quote.py \ + test_ca.in \ + test_chain.in \ + test_cert.in \ + test_cms.in \ + test_crypto.in \ + test_nist.in \ + test_nist2.in \ + test_nist_cert.in \ + test_nist_pkcs12.in \ + test_pkcs11.in \ + test_java_pkcs11.in \ + test_query.in \ + test_req.in \ + test_windows.in \ + tst-crypto-available1 \ + tst-crypto-available2 \ + tst-crypto-available3 \ + tst-crypto-select \ + tst-crypto-select1 \ + tst-crypto-select2 \ + tst-crypto-select3 \ + tst-crypto-select4 \ + tst-crypto-select5 \ + tst-crypto-select6 \ + tst-crypto-select7 \ + data/PKITS_data.zip \ + data/eccurve.pem \ + data/https.crt \ + data/https.key \ + data/mkcert.sh \ + data/nist-result2 \ + data/n0ll.pem \ + data/secp256r1TestCA.cert.pem \ + data/secp256r1TestCA.key.pem \ + data/secp256r1TestCA.pem \ + data/secp256r2TestClient.cert.pem \ + data/secp256r2TestClient.key.pem \ + data/secp256r2TestClient.pem \ + data/secp256r2TestServer.cert.pem \ + data/secp256r2TestServer.key.pem \ + data/secp256r2TestServer.pem \ + data/bleichenbacher-bad.pem \ + data/bleichenbacher-good.pem \ + data/bleichenbacher-sf-pad-correct.pem \ + data/ca.crt \ + data/ca.key \ + data/crl1.crl \ + data/crl1.der \ + data/gen-req.sh \ + data/j.pem \ + data/kdc.crt \ + data/kdc.key \ + data/key.der \ + data/key2.der \ + data/nist-data \ + data/nist-data2 \ + data/no-proxy-test.crt \ + data/no-proxy-test.key \ + data/ocsp-req1.der \ + data/ocsp-req2.der \ + data/ocsp-resp1-2.der \ + data/ocsp-resp1-3.der \ + data/ocsp-resp1-ca.der \ + data/ocsp-resp1-keyhash.der \ + data/ocsp-resp1-ocsp-no-cert.der \ + data/ocsp-resp1-ocsp.der \ + data/ocsp-resp1.der \ + data/ocsp-resp2.der \ + data/ocsp-responder.crt \ + data/ocsp-responder.key \ + data/openssl.1.0.cnf \ + data/openssl.1.1.cnf \ + data/pkinit-proxy-chain.crt \ + data/pkinit-proxy.crt \ + data/pkinit-proxy.key \ + data/pkinit-pw.key \ + data/pkinit.crt \ + data/pkinit.key \ + data/pkinit-ec.crt \ + data/pkinit-ec.key \ + data/proxy-level-test.crt \ + data/proxy-level-test.key \ + data/proxy-test.crt \ + data/proxy-test.key \ + data/proxy10-child-test.crt \ + data/proxy10-child-test.key \ + data/proxy10-child-child-test.crt \ + data/proxy10-child-child-test.key \ + data/proxy10-test.crt \ + data/proxy10-test.key \ + data/revoke.crt \ + data/revoke.key \ + data/sf-class2-root.pem \ + data/static-file \ + data/sub-ca.crt \ + data/sub-ca.key \ + data/sub-cert.crt \ + data/sub-cert.key \ + data/sub-cert.p12 \ + data/test-ds-only.crt \ + data/test-ds-only.key \ + data/test-enveloped-aes-128 \ + data/test-enveloped-aes-256 \ + data/test-enveloped-des \ + data/test-enveloped-des-ede3 \ + data/test-enveloped-rc2-128 \ + data/test-enveloped-rc2-40 \ + data/test-enveloped-rc2-64 \ + data/test-ke-only.crt \ + data/test-ke-only.key \ + data/test-nopw.p12 \ + data/test-pw.key \ + data/test-signed-data \ + data/test-signed-data-noattr \ + data/test-signed-data-noattr-nocerts \ + data/test-signed-sha-1 \ + data/test-signed-sha-256 \ + data/test-signed-sha-512 \ + data/test.combined.crt \ + data/test.crt \ + data/test.key \ + data/test.p12 \ + data/win-u16-in-printablestring.der \ + data/yutaka-pad-broken-ca.pem \ + data/yutaka-pad-broken-cert.pem \ + data/yutaka-pad-ok-ca.pem \ + data/yutaka-pad-ok-cert.pem \ + data/yutaka-pad.key diff --git a/third_party/heimdal/lib/hx509/NTMakefile b/third_party/heimdal/lib/hx509/NTMakefile new file mode 100644 index 0000000..4d5ff09 --- /dev/null +++ b/third_party/heimdal/lib/hx509/NTMakefile @@ -0,0 +1,180 @@ +######################################################################## +# +# Copyright (c) 2009-2017, Secure Endpoints Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +RELDIR=lib\hx509 +intcflags=-I$(OBJ) +localcflags=-DASN1_LIB + +!include ../../windows/NTMakefile.w32 + +libhx509_la_OBJS = \ + $(OBJ)\ca.obj \ + $(OBJ)\cert.obj \ + $(OBJ)\cms.obj \ + $(OBJ)\collector.obj \ + $(OBJ)\crypto.obj \ + $(OBJ)\crypto-ec.obj \ + $(OBJ)\error.obj \ + $(OBJ)\env.obj \ + $(OBJ)\file.obj \ + $(OBJ)\hx509_err.obj \ + $(OBJ)\sel.obj \ + $(OBJ)\sel-gram.obj \ + $(OBJ)\sel-lex.obj \ + $(OBJ)\keyset.obj \ + $(OBJ)\ks_dir.obj \ + $(OBJ)\ks_file.obj \ + $(OBJ)\ks_mem.obj \ + $(OBJ)\ks_null.obj \ + $(OBJ)\ks_p11.obj \ + $(OBJ)\ks_p12.obj \ + $(OBJ)\ks_keychain.obj \ + $(OBJ)\lock.obj \ + $(OBJ)\name.obj \ + $(OBJ)\peer.obj \ + $(OBJ)\print.obj \ + $(OBJ)\softp11.obj \ + $(OBJ)\req.obj \ + $(OBJ)\revoke.obj + +$(LIBHX509): $(libhx509_la_OBJS) + $(LIBCON) + +dist_libhx509_la_SOURCES = \ + $(SRCDIR)\ca.c \ + $(SRCDIR)\cert.c \ + $(SRCDIR)\cms.c \ + $(SRCDIR)\collector.c \ + $(SRCDIR)\crypto.c \ + $(SRCDIR)\crypto-ec.c \ + $(SRCDIR)\doxygen.c \ + $(SRCDIR)\error.c \ + $(SRCDIR)\env.c \ + $(SRCDIR)\file.c \ + $(SRCDIR)\hx509.h \ + $(SRCDIR)\hx_locl.h \ + $(SRCDIR)\sel.c \ + $(SRCDIR)\sel.h \ + $(SRCDIR)\sel-gram.y \ + $(SRCDIR)\sel-lex.l \ + $(SRCDIR)\keyset.c \ + $(SRCDIR)\ks_dir.c \ + $(SRCDIR)\ks_file.c \ + $(SRCDIR)\ks_mem.c \ + $(SRCDIR)\ks_null.c \ + $(SRCDIR)\ks_p11.c \ + $(SRCDIR)\ks_p12.c \ + $(SRCDIR)\ks_keychain.c \ + $(SRCDIR)\lock.c \ + $(SRCDIR)\name.c \ + $(SRCDIR)\peer.c \ + $(SRCDIR)\print.c \ + $(SRCDIR)\softp11.c \ + $(SRCDIR)\ref\pkcs11.h \ + $(SRCDIR)\req.c \ + $(SRCDIR)\revoke.c + +{}.c{$(OBJ)}.obj:: + $(C2OBJ_P) -DBUILD_HX509_LIB -DASN1_LIB + +{$(OBJ)}.c{$(OBJ)}.obj:: + $(C2OBJ_P) -DBUILD_HX509_LIB -DASN1_LIB + +asn1_compile=$(BINDIR)\asn1_compile.exe + +INCFILES= \ + $(INCDIR)\hx509.h \ + $(INCDIR)\hx509-protos.h \ + $(INCDIR)\hx509-private.h \ + $(INCDIR)\hx509_err.h + +hxtool.c: $(OBJ)\hxtool-commands.h + +SLC=$(BINDIR)\slc.exe + +$(OBJ)\hxtool-commands.c $(OBJ)\hxtool-commands.h: hxtool-commands.in $(SLC) + cd $(OBJ) + $(CP) $(SRCDIR)\hxtool-commands.in $(OBJ)\hxtool-commands.in + $(SLC) hxtool-commands.in + cd $(SRCDIR) + +$(BINDIR)\hxtool.exe: $(OBJ)\tool\hxtool.obj $(OBJ)\tool\hxtool-commands.obj $(LIBHEIMDAL) $(OBJ)\hxtool-version.res + $(EXECONLINK) $(LIBHEIMDAL) $(LIBROKEN) $(LIBSL) $(LIBVERS) $(LIBCOMERR) $(LIB_openssl_crypto) + $(EXEPREP) + +$(OBJ)\hx509-protos.h: + cd $(OBJ) + $(PERL) $(SRCDIR)\..\..\cf\make-proto.pl -R "^(_|^C)" -E HX509_LIB -q -P remove -o hx509-protos.h $(dist_libhx509_la_SOURCES) || $(RM) -f hx509-protos.h + cd $(SRCDIR) + +$(OBJ)\hx509-private.h: + cd $(OBJ) + $(PERL) $(SRCDIR)\..\..\cf\make-proto.pl -q -P remove -p hx509-private.h $(dist_libhx509_la_SOURCES) || $(RM) -f hx509-private.h + cd $(SRCDIR) + +$(OBJ)\hx509_err.c $(OBJ)\hx509_err.h: hx509_err.et + cd $(OBJ) + $(BINDIR)\compile_et.exe $(SRCDIR)\hx509_err.et + cd $(SRCDIR) + +$(OBJ)\sel-gram.obj: $(OBJ)\sel-gram.c + $(C2OBJ) -I$(SRCDIR) + +$(OBJ)\sel-lex.obj: $(OBJ)\sel-lex.c + $(C2OBJ) -I$(SRCDIR) -I$(OBJ) -DYY_NO_UNISTD_H + +$(OBJ)\sel-gram.c: sel-gram.y + $(YACC) -o $@ --defines=$(OBJ)\sel-gram.h sel-gram.y + +$(OBJ)\sel-lex.c: sel-lex.l + $(LEX) -P_hx509_sel_yy -o$@ sel-lex.l + +all:: $(INCFILES) $(LIBHX509) + +prep:: mktooldir + +mktooldir: +! if !exist($(OBJ)\tool) + $(MKDIR) $(OBJ)\tool +! endif + +all-tools:: $(BINDIR)\hxtool.exe + +clean:: + -$(RM) $(BINDIR)\hxtool.* + -$(RM) $(OBJ)\tool\*.* + +{}.c{$(OBJ)\tool}.obj:: + $(C2OBJ_C) /Fd$(OBJ)\tool\ /Fo$(OBJ)\tool\ $(MPOPT) /UASN1_LIB $< + +{$(OBJ)}.c{$(OBJ)\tool}.obj:: + $(C2OBJ_C) /Fd$(OBJ)\tool\ /Fo$(OBJ)\tool\ $(MPOPT) /UASN1_LIB $< + diff --git a/third_party/heimdal/lib/hx509/TODO b/third_party/heimdal/lib/hx509/TODO new file mode 100644 index 0000000..ecdfa8d --- /dev/null +++ b/third_party/heimdal/lib/hx509/TODO @@ -0,0 +1,61 @@ +Handle private_key_ops better, esp wrt ->key_oid + +Better support for keyex negotiation, DH and ECDH. + +x501 name + parsing + comparing (ldap canonlisation rules) + +DSA support +DSA2 support + +Rewrite the pkcs11 code to support the following: + + * Reset the pin on card change. + * Ref count the lock structure to make sure we have a + prompter when we need it. + * Add support for CK_TOKEN_INFO.CKF_PROTECTED_AUTHENTICATION_PATH + +x509 policy mappings support + +CRL delta support + +Qualified statement + https://bugzilla.mozilla.org/show_bug.cgi?id=277797#c2 + + +Signed Receipts + http://www.faqs.org/rfcs/rfc2634.html + chapter 2 + +tests + nist tests + name constrains + policy mappings + http://csrc.nist.gov/pki/testing/x509paths.html + + building path using Subject/Issuer vs SubjKeyID vs AuthKeyID + negative tests + all checksums + conditions/branches + +pkcs7 + handle pkcs7 support in CMS ? + +certificate request + generate pkcs10 request + from existing cert + generate CRMF request + pk-init KDC/client + web server/client + jabber server/client + email + + +x509 issues: + + OtherName is left unspecified, but it's used by other + specs. creating this hole where a application/CA can't specify + policy for SubjectAltName what covers whole space. For example, a + CA is trusted to provide authentication but not authorization. + diff --git a/third_party/heimdal/lib/hx509/ca.c b/third_party/heimdal/lib/hx509/ca.c new file mode 100644 index 0000000..3d62b93 --- /dev/null +++ b/third_party/heimdal/lib/hx509/ca.c @@ -0,0 +1,3093 @@ +/* + * Copyright (c) 2006 - 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" + +/** + * @page page_ca Hx509 CA functions + * + * See the library functions here: @ref hx509_ca + */ + +struct hx509_ca_tbs { + hx509_name subject; + SubjectPublicKeyInfo spki; + KeyUsage ku; + ExtKeyUsage eku; + GeneralNames san; + CertificatePolicies cps; + PolicyMappings pms; + heim_integer serial; + struct { + unsigned int proxy:1; + unsigned int ca:1; + unsigned int key:1; + unsigned int serial:1; + unsigned int domaincontroller:1; + unsigned int xUniqueID:1; + } flags; + time_t notBefore; + time_t notAfter; + HeimPkinitPrincMaxLifeSecs pkinitTicketMaxLife; + int pathLenConstraint; /* both for CA and Proxy */ + CRLDistributionPoints crldp; + heim_bit_string subjectUniqueID; + heim_bit_string issuerUniqueID; + AlgorithmIdentifier *sigalg; +}; + +/** + * Allocate an to-be-signed certificate object that will be converted + * into an certificate. + * + * @param context A hx509 context. + * @param tbs returned to-be-signed certicate object, free with + * hx509_ca_tbs_free(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_init(hx509_context context, hx509_ca_tbs *tbs) +{ + *tbs = calloc(1, sizeof(**tbs)); + if (*tbs == NULL) + return ENOMEM; + + return 0; +} + +/** + * Free an To Be Signed object. + * + * @param tbs object to free. + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_ca_tbs_free(hx509_ca_tbs *tbs) +{ + if (tbs == NULL || *tbs == NULL) + return; + + free_SubjectPublicKeyInfo(&(*tbs)->spki); + free_CertificatePolicies(&(*tbs)->cps); + free_PolicyMappings(&(*tbs)->pms); + free_GeneralNames(&(*tbs)->san); + free_ExtKeyUsage(&(*tbs)->eku); + der_free_heim_integer(&(*tbs)->serial); + free_CRLDistributionPoints(&(*tbs)->crldp); + der_free_bit_string(&(*tbs)->subjectUniqueID); + der_free_bit_string(&(*tbs)->issuerUniqueID); + if ((*tbs)->subject) + hx509_name_free(&(*tbs)->subject); + if ((*tbs)->sigalg) { + free_AlgorithmIdentifier((*tbs)->sigalg); + free((*tbs)->sigalg); + } + + memset(*tbs, 0, sizeof(**tbs)); + free(*tbs); + *tbs = NULL; +} + +/** + * Set the absolute time when the certificate is valid from. If not + * set the current time will be used. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param t time the certificated will start to be valid + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_set_notBefore(hx509_context context, + hx509_ca_tbs tbs, + time_t t) +{ + tbs->notBefore = t; + return 0; +} + +/** + * Set the absolute time when the certificate is valid to. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param t time when the certificate will expire + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_set_notAfter(hx509_context context, + hx509_ca_tbs tbs, + time_t t) +{ + tbs->notAfter = t; + return 0; +} + +/** + * Set the relative time when the certificiate is going to expire. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param delta seconds to the certificate is going to expire. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_set_notAfter_lifetime(hx509_context context, + hx509_ca_tbs tbs, + time_t delta) +{ + return hx509_ca_tbs_set_notAfter(context, tbs, time(NULL) + delta); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_set_pkinit_max_life(hx509_context context, + hx509_ca_tbs tbs, + time_t max_life) +{ + tbs->pkinitTicketMaxLife = max_life; + return 0; +} + +static const struct units templatebits[] = { + { "ExtendedKeyUsage", HX509_CA_TEMPLATE_EKU }, + { "KeyUsage", HX509_CA_TEMPLATE_KU }, + { "SPKI", HX509_CA_TEMPLATE_SPKI }, + { "notAfter", HX509_CA_TEMPLATE_NOTAFTER }, + { "notBefore", HX509_CA_TEMPLATE_NOTBEFORE }, + { "serial", HX509_CA_TEMPLATE_SERIAL }, + { "subject", HX509_CA_TEMPLATE_SUBJECT }, + { "pkinitMaxLife", HX509_CA_TEMPLATE_PKINIT_MAX_LIFE }, + { NULL, 0 } +}; + +/** + * Make of template units, use to build flags argument to + * hx509_ca_tbs_set_template() with parse_units(). + * + * @return an units structure. + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION const struct units * HX509_LIB_CALL +hx509_ca_tbs_template_units(void) +{ + return templatebits; +} + +/** + * Initialize the to-be-signed certificate object from a template certificate. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param flags bit field selecting what to copy from the template + * certificate. + * @param cert template certificate. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_set_template(hx509_context context, + hx509_ca_tbs tbs, + int flags, + hx509_cert cert) +{ + int ret; + + if (flags & HX509_CA_TEMPLATE_SUBJECT) { + if (tbs->subject) + hx509_name_free(&tbs->subject); + ret = hx509_cert_get_subject(cert, &tbs->subject); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to get subject from template"); + return ret; + } + } + if (flags & HX509_CA_TEMPLATE_SERIAL) { + der_free_heim_integer(&tbs->serial); + ret = hx509_cert_get_serialnumber(cert, &tbs->serial); + tbs->flags.serial = !ret; + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to copy serial number"); + return ret; + } + } + if (flags & HX509_CA_TEMPLATE_NOTBEFORE) + tbs->notBefore = hx509_cert_get_notBefore(cert); + if (flags & HX509_CA_TEMPLATE_NOTAFTER) + tbs->notAfter = hx509_cert_get_notAfter(cert); + if (flags & HX509_CA_TEMPLATE_SPKI) { + free_SubjectPublicKeyInfo(&tbs->spki); + ret = hx509_cert_get_SPKI(context, cert, &tbs->spki); + tbs->flags.key = !ret; + if (ret) + return ret; + } + if (flags & HX509_CA_TEMPLATE_KU) { + ret = _hx509_cert_get_keyusage(context, cert, &tbs->ku); + if (ret) + return ret; + } + if (flags & HX509_CA_TEMPLATE_EKU) { + ExtKeyUsage eku; + size_t i; + ret = _hx509_cert_get_eku(context, cert, &eku); + if (ret) + return ret; + for (i = 0; i < eku.len; i++) { + ret = hx509_ca_tbs_add_eku(context, tbs, &eku.val[i]); + if (ret) { + free_ExtKeyUsage(&eku); + return ret; + } + } + free_ExtKeyUsage(&eku); + } + if (flags & HX509_CA_TEMPLATE_PKINIT_MAX_LIFE) { + time_t max_life; + + if ((max_life = hx509_cert_get_pkinit_max_life(context, cert, 0)) > 0) + hx509_ca_tbs_set_pkinit_max_life(context, tbs, max_life); + } + return 0; +} + +/** + * Make the to-be-signed certificate object a CA certificate. If the + * pathLenConstraint is negative path length constraint is used. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param pathLenConstraint path length constraint, negative, no + * constraint. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_set_ca(hx509_context context, + hx509_ca_tbs tbs, + int pathLenConstraint) +{ + tbs->flags.ca = 1; + tbs->pathLenConstraint = pathLenConstraint; + return 0; +} + +/** + * Make the to-be-signed certificate object a proxy certificate. If the + * pathLenConstraint is negative path length constraint is used. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param pathLenConstraint path length constraint, negative, no + * constraint. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_set_proxy(hx509_context context, + hx509_ca_tbs tbs, + int pathLenConstraint) +{ + tbs->flags.proxy = 1; + tbs->pathLenConstraint = pathLenConstraint; + return 0; +} + + +/** + * Make the to-be-signed certificate object a windows domain controller certificate. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_set_domaincontroller(hx509_context context, + hx509_ca_tbs tbs) +{ + tbs->flags.domaincontroller = 1; + return 0; +} + +/** + * Set the subject public key info (SPKI) in the to-be-signed certificate + * object. SPKI is the public key and key related parameters in the + * certificate. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param spki subject public key info to use for the to-be-signed certificate object. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_set_spki(hx509_context context, + hx509_ca_tbs tbs, + const SubjectPublicKeyInfo *spki) +{ + int ret; + free_SubjectPublicKeyInfo(&tbs->spki); + ret = copy_SubjectPublicKeyInfo(spki, &tbs->spki); + tbs->flags.key = !ret; + return ret; +} + +/** + * Set the serial number to use for to-be-signed certificate object. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param serialNumber serial number to use for the to-be-signed + * certificate object. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_set_serialnumber(hx509_context context, + hx509_ca_tbs tbs, + const heim_integer *serialNumber) +{ + int ret; + der_free_heim_integer(&tbs->serial); + ret = der_copy_heim_integer(serialNumber, &tbs->serial); + tbs->flags.serial = !ret; + return ret; +} + +/** + * Copy elements of a CSR into a TBS, but only if all of them are authorized. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param req CSR + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_set_from_csr(hx509_context context, + hx509_ca_tbs tbs, + hx509_request req) +{ + hx509_san_type san_type; + heim_oid oid = { 0, 0 }; + KeyUsage ku; + size_t i; + char *s = NULL; + int ret; + + if (hx509_request_count_unauthorized(req)) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return EACCES; + } + + ret = hx509_request_get_ku(context, req, &ku); + if (ret == 0 && KeyUsage2int(ku)) + ret = hx509_ca_tbs_add_ku(context, tbs, ku); + + for (i = 0; ret == 0; i++) { + free(s); s = NULL; + der_free_oid(&oid); + ret = hx509_request_get_eku(req, i, &s); + if (ret == 0) + ret = der_parse_heim_oid(s, ".", &oid); + if (ret == 0) + ret = hx509_ca_tbs_add_eku(context, tbs, &oid); + } + if (ret == HX509_NO_ITEM) + ret = 0; + + for (i = 0; ret == 0; i++) { + free(s); s = NULL; + ret = hx509_request_get_san(req, i, &san_type, &s); + if (ret == 0) + ret = hx509_ca_tbs_add_san(context, tbs, san_type, s); + } + if (ret == HX509_NO_ITEM) + ret = 0; + + der_free_oid(&oid); + free(s); + return ret; +} + +/** + * An an extended key usage to the to-be-signed certificate object. + * Duplicates will detected and not added. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param oid extended key usage to add. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_add_ku(hx509_context context, + hx509_ca_tbs tbs, + KeyUsage ku) +{ + tbs->ku = ku; + return 0; +} + +/** + * An an extended key usage to the to-be-signed certificate object. + * Duplicates will detected and not added. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param oid extended key usage to add. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_add_eku(hx509_context context, + hx509_ca_tbs tbs, + const heim_oid *oid) +{ + void *ptr; + int ret; + unsigned i; + + /* search for duplicates */ + for (i = 0; i < tbs->eku.len; i++) { + if (der_heim_oid_cmp(oid, &tbs->eku.val[i]) == 0) + return 0; + } + + ptr = realloc(tbs->eku.val, sizeof(tbs->eku.val[0]) * (tbs->eku.len + 1)); + if (ptr == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + tbs->eku.val = ptr; + ret = der_copy_oid(oid, &tbs->eku.val[tbs->eku.len]); + if (ret) { + hx509_set_error_string(context, 0, ret, "out of memory"); + return ret; + } + tbs->eku.len += 1; + return 0; +} + +/** + * Add a certificate policy to the to-be-signed certificate object. Duplicates + * will detected and not added. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param oid policy OID. + * @param cps_uri CPS URI to qualify policy with. + * @param user_notice user notice display text to qualify policy with. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_add_pol(hx509_context context, + hx509_ca_tbs tbs, + const heim_oid *oid, + const char *cps_uri, + const char *user_notice) +{ + PolicyQualifierInfos pqis; + PolicyQualifierInfo pqi; + PolicyInformation pi; + size_t i, size; + int ret = 0; + + /* search for duplicates */ + for (i = 0; i < tbs->cps.len; i++) { + if (der_heim_oid_cmp(oid, &tbs->cps.val[i].policyIdentifier) == 0) + return 0; + } + + memset(&pi, 0, sizeof(pi)); + memset(&pqi, 0, sizeof(pqi)); + memset(&pqis, 0, sizeof(pqis)); + + pi.policyIdentifier = *oid; + if (cps_uri) { + CPSuri uri; + + uri.length = strlen(cps_uri); + uri.data = (void *)(uintptr_t)cps_uri; + pqi.policyQualifierId = asn1_oid_id_pkix_qt_cps; + + ASN1_MALLOC_ENCODE(CPSuri, + pqi.qualifier.data, + pqi.qualifier.length, + &uri, &size, ret); + if (ret == 0) { + ret = add_PolicyQualifierInfos(&pqis, &pqi); + free_heim_any(&pqi.qualifier); + } + } + if (ret == 0 && user_notice) { + DisplayText dt; + UserNotice un; + + dt.element = choice_DisplayText_utf8String; + dt.u.utf8String = (void *)(uintptr_t)user_notice; + un.explicitText = &dt; + un.noticeRef = 0; + + pqi.policyQualifierId = asn1_oid_id_pkix_qt_unotice; + ASN1_MALLOC_ENCODE(UserNotice, + pqi.qualifier.data, + pqi.qualifier.length, + &un, &size, ret); + if (ret == 0) { + ret = add_PolicyQualifierInfos(&pqis, &pqi); + free_heim_any(&pqi.qualifier); + } + } + + pi.policyQualifiers = pqis.len ? &pqis : 0; + + if (ret == 0) + ret = add_CertificatePolicies(&tbs->cps, &pi); + + free_PolicyQualifierInfos(&pqis); + return ret; +} + +/** + * Add a certificate policy mapping to the to-be-signed certificate object. + * Duplicates will detected and not added. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param issuer issuerDomainPolicy policy OID. + * @param subject subjectDomainPolicy policy OID. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_add_pol_mapping(hx509_context context, + hx509_ca_tbs tbs, + const heim_oid *issuer, + const heim_oid *subject) +{ + PolicyMapping pm; + size_t i; + + /* search for duplicates */ + for (i = 0; i < tbs->pms.len; i++) { + PolicyMapping *pmp = &tbs->pms.val[i]; + if (der_heim_oid_cmp(issuer, &pmp->issuerDomainPolicy) == 0 && + der_heim_oid_cmp(subject, &pmp->subjectDomainPolicy) == 0) + return 0; + } + + memset(&pm, 0, sizeof(pm)); + pm.issuerDomainPolicy = *issuer; + pm.subjectDomainPolicy = *subject; + return add_PolicyMappings(&tbs->pms, &pm); +} + +/** + * Add CRL distribution point URI to the to-be-signed certificate + * object. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param uri uri to the CRL. + * @param issuername name of the issuer. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_add_crl_dp_uri(hx509_context context, + hx509_ca_tbs tbs, + const char *uri, + hx509_name issuername) +{ + DistributionPointName dpn; + DistributionPoint dp; + GeneralNames crlissuer; + GeneralName gn, ign; + Name in; + int ret; + + memset(&dp, 0, sizeof(dp)); + memset(&gn, 0, sizeof(gn)); + memset(&ign, 0, sizeof(ign)); + memset(&in, 0, sizeof(in)); + gn.element = choice_GeneralName_uniformResourceIdentifier; + gn.u.uniformResourceIdentifier.data = rk_UNCONST(uri); + gn.u.uniformResourceIdentifier.length = strlen(uri); + dpn.element = choice_DistributionPointName_fullName; + dpn.u.fullName.len = 1; + dpn.u.fullName.val = &gn; + dp.distributionPoint = &dpn; + + if (issuername) { + ign.element = choice_GeneralName_directoryName; + ret = hx509_name_to_Name(issuername, &ign.u.directoryName); + if (ret) { + hx509_set_error_string(context, 0, ret, "out of memory"); + return ret; + } + crlissuer.len = 1; + crlissuer.val = &ign; + dp.cRLIssuer = &crlissuer; + } + + ret = add_CRLDistributionPoints(&tbs->crldp, &dp); + if (issuername) + free_Name(&ign.u.directoryName); + + if (ret) + hx509_set_error_string(context, 0, ret, "out of memory"); + return ret; +} + +/** + * Add Subject Alternative Name otherName to the to-be-signed + * certificate object. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param oid the oid of the OtherName. + * @param os data in the other name. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_add_san_otherName(hx509_context context, + hx509_ca_tbs tbs, + const heim_oid *oid, + const heim_octet_string *os) +{ + GeneralName gn; + + memset(&gn, 0, sizeof(gn)); + gn.element = choice_GeneralName_otherName; + gn.u.otherName.type_id = *oid; + gn.u.otherName.value = *os; + + return add_GeneralNames(&tbs->san, &gn); +} + +static +int +dequote_strndup(hx509_context context, const char *in, size_t len, char **out) +{ + size_t i, k; + char *s; + + *out = NULL; + if ((s = malloc(len + 1)) == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "malloc: out of memory"); + return ENOMEM; + } + + for (k = i = 0; i < len; i++) { + if (in[i] == '\\') { + switch (in[++i]) { + case 't': s[k++] = '\t'; break; + case 'b': s[k++] = '\b'; break; + case 'n': s[k++] = '\n'; break; + case '0': + for (i++; i < len; i++) { + if (in[i] == '\0') + break; + if (in[i++] == '\\' && in[i] == '0') + continue; + hx509_set_error_string(context, 0, + HX509_PARSING_NAME_FAILED, + "embedded NULs not supported in " + "PKINIT SANs"); + free(s); + return HX509_PARSING_NAME_FAILED; + } + break; + case '\0': + hx509_set_error_string(context, 0, + HX509_PARSING_NAME_FAILED, + "trailing unquoted backslashes not " + "allowed in PKINIT SANs"); + free(s); + return HX509_PARSING_NAME_FAILED; + default: s[k++] = in[i]; break; + } + } else { + s[k++] = in[i]; + } + } + s[k] = '\0'; + + *out = s; + return 0; +} + +int +_hx509_make_pkinit_san(hx509_context context, + const char *principal, + heim_octet_string *os) +{ + KRB5PrincipalName p; + size_t size; + int ret; + + os->data = NULL; + os->length = 0; + memset(&p, 0, sizeof(p)); + + /* Parse principal */ + { + const char *str, *str_start; + size_t n, i; + + /* Count number of components */ + n = 1; + for (str = principal; *str != '\0' && *str != '@'; str++) { + if (*str == '\\') { + if (str[1] == '\0') { + ret = HX509_PARSING_NAME_FAILED; + hx509_set_error_string(context, 0, ret, + "trailing \\ in principal name"); + goto out; + } + str++; + } else if(*str == '/') { + n++; + } else if(*str == '@') { + break; + } + } + if (*str != '@') { + /* Note that we allow the realm to be empty */ + ret = HX509_PARSING_NAME_FAILED; + hx509_set_error_string(context, 0, ret, "Missing @ in principal"); + goto out; + }; + + p.principalName.name_string.val = + calloc(n, sizeof(*p.principalName.name_string.val)); + if (p.principalName.name_string.val == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "malloc: out of memory"); + goto out; + } + p.principalName.name_string.len = n; + p.principalName.name_type = KRB5_NT_PRINCIPAL; + + for (i = 0, str_start = str = principal; *str != '\0'; str++) { + if (*str=='\\') { + str++; + } else if(*str == '/') { + /* Note that we allow components to be empty */ + ret = dequote_strndup(context, str_start, str - str_start, + &p.principalName.name_string.val[i++]); + if (ret) + goto out; + str_start = str + 1; + } else if(*str == '@') { + ret = dequote_strndup(context, str_start, str - str_start, + &p.principalName.name_string.val[i++]); + if (ret == 0) + ret = dequote_strndup(context, str + 1, strlen(str + 1), &p.realm); + if (ret) + goto out; + break; + } + } + } + + ASN1_MALLOC_ENCODE(KRB5PrincipalName, os->data, os->length, &p, &size, ret); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + if (size != os->length) + _hx509_abort("internal ASN.1 encoder error"); + +out: + free_KRB5PrincipalName(&p); + return ret; +} + +static int +add_ia5string_san(hx509_context context, + hx509_ca_tbs tbs, + const heim_oid *oid, + const char *string) +{ + SRVName ustring; + heim_octet_string os; + size_t size; + int ret; + + ustring.data = (void *)(uintptr_t)string; + ustring.length = strlen(string); + + os.length = 0; + os.data = NULL; + + ASN1_MALLOC_ENCODE(SRVName, os.data, os.length, &ustring, &size, ret); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + return ret; + } + if (size != os.length) + _hx509_abort("internal ASN.1 encoder error"); + + ret = hx509_ca_tbs_add_san_otherName(context, tbs, oid, &os); + free(os.data); + return ret; +} + +/** + * Add DNSSRV Subject Alternative Name to the to-be-signed certificate object. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param dnssrv An ASCII string of the for _Service.Name. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_add_san_dnssrv(hx509_context context, + hx509_ca_tbs tbs, + const char *dnssrv) +{ + size_t i, len; + + /* Minimal DNSSRV input validation */ + if (dnssrv == 0 || dnssrv[0] != '_') { + hx509_set_error_string(context, 0, EINVAL, "Invalid DNSSRV name"); + return EINVAL; + } + for (i = 1, len = strlen(dnssrv); i < len; i++) { + if (dnssrv[i] == '.' && dnssrv[i + 1] != '\0') + break; + } + if (i == len) { + hx509_set_error_string(context, 0, EINVAL, "Invalid DNSSRV name"); + return EINVAL; + } + + return add_ia5string_san(context, tbs, + &asn1_oid_id_pkix_on_dnsSRV, dnssrv); +} + +/** + * Add Kerberos Subject Alternative Name to the to-be-signed + * certificate object. The principal string is a UTF8 string. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param principal Kerberos principal to add to the certificate. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_add_san_pkinit(hx509_context context, + hx509_ca_tbs tbs, + const char *principal) +{ + heim_octet_string os; + int ret; + + ret = _hx509_make_pkinit_san(context, principal, &os); + if (ret == 0) + ret = hx509_ca_tbs_add_san_otherName(context, tbs, + &asn1_oid_id_pkinit_san, &os); + free(os.data); + return ret; +} + +/* + * + */ + +static int +add_utf8_san(hx509_context context, + hx509_ca_tbs tbs, + const heim_oid *oid, + const char *string) +{ + const PKIXXmppAddr ustring = (const PKIXXmppAddr)(uintptr_t)string; + heim_octet_string os; + size_t size; + int ret; + + os.length = 0; + os.data = NULL; + + ASN1_MALLOC_ENCODE(PKIXXmppAddr, os.data, os.length, &ustring, &size, ret); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + return ret; + } + if (size != os.length) + _hx509_abort("internal ASN.1 encoder error"); + + ret = hx509_ca_tbs_add_san_otherName(context, tbs, oid, &os); + free(os.data); + return ret; +} + +/** + * Add Microsoft UPN Subject Alternative Name to the to-be-signed + * certificate object. The principal string is a UTF8 string. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param principal Microsoft UPN string. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_add_san_ms_upn(hx509_context context, + hx509_ca_tbs tbs, + const char *principal) +{ + return add_utf8_san(context, tbs, &asn1_oid_id_pkinit_ms_san, principal); +} + +/** + * Add a Jabber/XMPP jid Subject Alternative Name to the to-be-signed + * certificate object. The jid is an UTF8 string. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param jid string of an a jabber id in UTF8. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_add_san_jid(hx509_context context, + hx509_ca_tbs tbs, + const char *jid) +{ + return add_utf8_san(context, tbs, &asn1_oid_id_pkix_on_xmppAddr, jid); +} + + +/** + * Add a Subject Alternative Name hostname to to-be-signed certificate + * object. A domain match starts with ., an exact match does not. + * + * Example of a an domain match: .domain.se matches the hostname + * host.domain.se. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param dnsname a hostame. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_add_san_hostname(hx509_context context, + hx509_ca_tbs tbs, + const char *dnsname) +{ + GeneralName gn; + + memset(&gn, 0, sizeof(gn)); + gn.element = choice_GeneralName_dNSName; + gn.u.dNSName.data = rk_UNCONST(dnsname); + gn.u.dNSName.length = strlen(dnsname); + + return add_GeneralNames(&tbs->san, &gn); +} + +/** + * Add a Subject Alternative Name rfc822 (email address) to + * to-be-signed certificate object. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param rfc822Name a string to a email address. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_add_san_rfc822name(hx509_context context, + hx509_ca_tbs tbs, + const char *rfc822Name) +{ + GeneralName gn; + + memset(&gn, 0, sizeof(gn)); + gn.element = choice_GeneralName_rfc822Name; + gn.u.rfc822Name.data = rk_UNCONST(rfc822Name); + gn.u.rfc822Name.length = strlen(rfc822Name); + + return add_GeneralNames(&tbs->san, &gn); +} + +/* + * PermanentIdentifier is one SAN for naming devices with TPMs after their + * endorsement keys or EK certificates. See TPM 2.0 Keys for Device Identity + * and Attestation, Version 1.00, Revision 2, 9/17/2020 (DRAFT). + * + * The text on the form of permanent identifiers for TPM endorsement keys sans + * certificates is clearly problematic, saying: "When the TPM does not have an + * EK certificate, the identifierValue is a digest of a concatenation of the + * UTF8 string “EkPubkey” (terminating NULL not included) with the binary EK + * public key", but since arbitrary binary is not necessarily valid UTF-8... + * and since NULs embedded in UTF-8 might be OK in some contexts but really + * isn't in C (and Heimdal's ASN.1 compiler does not allow NULs in the + * middle of strings)... That just cannot be correct. Since elsewhere the TCG + * specs use the hex encoding of the SHA-256 digest of the DER encoding of + * public keys, that's what we should support in Heimdal, and maybe send in a + * comment. + * + * Also, even where one should use hex encoding of the SHA-256 digest of the + * DER encoding of public keys, how should the public keys be represented? + * Presumably as SPKIs, with all the required parameters and no more. + */ + +/** + * Add a Subject Alternative Name of PermanentIdentifier type to a to-be-signed + * certificate object. The permanent identifier form for TPM endorsement key + * certificates is the hex encoding of the SHA-256 digest of the DER encoding + * of the certificate. The permanent identifier form for TPM endorsement keys + * are of the form "EkPubkey<public-key>", where the form of <public-key> is + * not well specified at this point. It is the caller's responsibility to + * format the identifierValue. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param str permanent identifier name in the form "[<assigner-oid>]:[<id>]". + * @param assigner The OID of an assigner. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_add_san_permanentIdentifier_string(hx509_context context, + hx509_ca_tbs tbs, + const char *str) +{ + const heim_oid *found = NULL; + heim_oid oid; + const char *oidstr, *id; + char *freeme, *p; + int ret; + + if ((freeme = strdup(str)) == NULL) + return hx509_enomem(context); + + oidstr = freeme; + p = strchr(freeme, ':'); + if (!p) { + hx509_set_error_string(context, 0, EINVAL, + "Invalid PermanentIdentifier string (should be \"[<oid>]:[<id>]\")", + oidstr); + free(freeme); + return EINVAL; + } + if (p) { + *(p++) = '\0'; + id = p; + } + if (oidstr[0] != '\0') { + ret = der_find_heim_oid_by_name(oidstr, &found); + if (ret) { + ret = der_parse_heim_oid(oidstr, " .", &oid); + if (ret == 0) + found = &oid; + } + } + ret = hx509_ca_tbs_add_san_permanentIdentifier(context, tbs, id, found); + if (found == &oid) + der_free_oid(&oid); + free(freeme); + return ret; +} + +/** + * Add a Subject Alternative Name of PermanentIdentifier type to a to-be-signed + * certificate object. The permanent identifier form for TPM endorsement key + * certificates is the hex encoding of the SHA-256 digest of the DER encoding + * of the certificate. The permanent identifier form for TPM endorsement keys + * are of the form "EkPubkey<public-key>", where the form of <public-key> is + * not well specified at this point. It is the caller's responsibility to + * format the identifierValue. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param identifierValue The permanent identifier name. + * @param assigner The OID of an assigner. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_add_san_permanentIdentifier(hx509_context context, + hx509_ca_tbs tbs, + const char *identifierValue, + const heim_oid *assigner) +{ + PermanentIdentifier pi; + heim_utf8_string s = (void *)(uintptr_t)identifierValue; + heim_octet_string os; + size_t size; + int ret; + + pi.identifierValue = &s; + pi.assigner = (heim_oid*)(uintptr_t)assigner; + os.length = 0; + os.data = NULL; + + ASN1_MALLOC_ENCODE(PermanentIdentifier, os.data, os.length, &pi, &size, + ret); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + return ret; + } + if (size != os.length) + _hx509_abort("internal ASN.1 encoder error"); + + ret = hx509_ca_tbs_add_san_otherName(context, tbs, + &asn1_oid_id_pkix_on_permanentIdentifier, + &os); + free(os.data); + return ret; +} + +/** + * Add a Subject Alternative Name of HardwareModuleName type to a to-be-signed + * certificate object. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param str a string of the form "<oid>:<serial>". + * @param hwserial The serial number. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_add_san_hardwareModuleName_string(hx509_context context, + hx509_ca_tbs tbs, + const char *str) +{ + const heim_oid *found = NULL; + heim_oid oid; + const char *oidstr, *sno; + char *freeme, *p; + int ret; + + if ((freeme = strdup(str)) == NULL) + return hx509_enomem(context); + + oidstr = freeme; + p = strchr(freeme, ':'); + if (!p) { + hx509_set_error_string(context, 0, EINVAL, + "Invalid HardwareModuleName string (should be " + "\"<oid>:<serial>\")", + oidstr); + free(freeme); + return EINVAL; + } + if (p) { + *(p++) = '\0'; + sno = p; + } + if (oidstr[0] == '\0') { + found = &asn1_oid_tcg_tpm20; + } else { + ret = der_find_heim_oid_by_name(oidstr, &found); + if (ret) { + ret = der_parse_heim_oid(oidstr, " .", &oid); + if (ret == 0) + found = &oid; + } + } + if (!found) { + hx509_set_error_string(context, 0, EINVAL, + "Could not resolve or parse OID \"%s\"", + oidstr); + free(freeme); + return EINVAL; + } + ret = hx509_ca_tbs_add_san_hardwareModuleName(context, tbs, found, sno); + if (found == &oid) + der_free_oid(&oid); + free(freeme); + return ret; +} + +/** + * Add a Subject Alternative Name of HardwareModuleName type to a to-be-signed + * certificate object. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param hwtype The hardwar module type (e.g., `&asn1_oid_tcg_tpm20'). + * @param hwserial The serial number. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_add_san_hardwareModuleName(hx509_context context, + hx509_ca_tbs tbs, + const heim_oid *hwtype, + const char *hwserial) +{ + HardwareModuleName hm; + heim_octet_string os; + size_t size; + int ret; + + hm.hwType = *hwtype; + hm.hwSerialNum.data = (void *)(uintptr_t)hwserial; + hm.hwSerialNum.length = strlen(hwserial); + os.length = 0; + os.data = NULL; + + ASN1_MALLOC_ENCODE(HardwareModuleName, os.data, os.length, &hm, &size, + ret); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + return ret; + } + if (size != os.length) + _hx509_abort("internal ASN.1 encoder error"); + + ret = hx509_ca_tbs_add_san_otherName(context, tbs, + &asn1_oid_id_on_hardwareModuleName, + &os); + free(os.data); + return ret; +} + +/** + * Add a Subject Alternative Name of the given type to the + * to-be-signed certificate object. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param rfc822Name a string to a email address. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_add_san(hx509_context context, + hx509_ca_tbs tbs, + hx509_san_type type, + const char *s) +{ + switch (type) { + case HX509_SAN_TYPE_EMAIL: + return hx509_ca_tbs_add_san_rfc822name(context, tbs, s); + case HX509_SAN_TYPE_DNSNAME: + return hx509_ca_tbs_add_san_hostname(context, tbs, s); + case HX509_SAN_TYPE_DN: + return ENOTSUP; + case HX509_SAN_TYPE_REGISTERED_ID: + return ENOTSUP; + case HX509_SAN_TYPE_XMPP: + return hx509_ca_tbs_add_san_jid(context, tbs, s); + case HX509_SAN_TYPE_PKINIT: + return hx509_ca_tbs_add_san_pkinit(context, tbs, s); + case HX509_SAN_TYPE_MS_UPN: + return hx509_ca_tbs_add_san_ms_upn(context, tbs, s); + default: + return ENOTSUP; + } +} + +/** + * Set the subject name of a to-be-signed certificate object. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param subject the name to set a subject. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_set_subject(hx509_context context, + hx509_ca_tbs tbs, + hx509_name subject) +{ + if (tbs->subject) + hx509_name_free(&tbs->subject); + return hx509_name_copy(context, subject, &tbs->subject); +} + +/** + * Set the issuerUniqueID and subjectUniqueID + * + * These are only supposed to be used considered with version 2 + * certificates, replaced by the two extensions SubjectKeyIdentifier + * and IssuerKeyIdentifier. This function is to allow application + * using legacy protocol to issue them. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param issuerUniqueID to be set + * @param subjectUniqueID to be set + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_set_unique(hx509_context context, + hx509_ca_tbs tbs, + const heim_bit_string *subjectUniqueID, + const heim_bit_string *issuerUniqueID) +{ + int ret; + + der_free_bit_string(&tbs->subjectUniqueID); + der_free_bit_string(&tbs->issuerUniqueID); + + if (subjectUniqueID) { + ret = der_copy_bit_string(subjectUniqueID, &tbs->subjectUniqueID); + if (ret) + return ret; + } + + if (issuerUniqueID) { + ret = der_copy_bit_string(issuerUniqueID, &tbs->issuerUniqueID); + if (ret) + return ret; + } + + return 0; +} + +/** + * Expand the the subject name in the to-be-signed certificate object + * using hx509_name_expand(). + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param env environment variable to expand variables in the subject + * name, see hx509_env_init(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_subject_expand(hx509_context context, + hx509_ca_tbs tbs, + hx509_env env) +{ + return hx509_name_expand(context, tbs->subject, env); +} + +/** + * Get the name of a to-be-signed certificate object. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * + * @return An hx509 name. + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION hx509_name HX509_LIB_CALL +hx509_ca_tbs_get_name(hx509_ca_tbs tbs) +{ + return tbs->subject; +} + +/** + * Set signature algorithm on the to be signed certificate + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param sigalg signature algorithm to use + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_set_signature_algorithm(hx509_context context, + hx509_ca_tbs tbs, + const AlgorithmIdentifier *sigalg) +{ + int ret; + + tbs->sigalg = calloc(1, sizeof(*tbs->sigalg)); + if (tbs->sigalg == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "Out of memory"); + return ENOMEM; + } + ret = copy_AlgorithmIdentifier(sigalg, tbs->sigalg); + if (ret) { + free(tbs->sigalg); + tbs->sigalg = NULL; + return ret; + } + return 0; +} + +/* + * + */ + +static int +add_extension(hx509_context context, + TBSCertificate *tbsc, + int critical_flag, + const heim_oid *oid, + const heim_octet_string *data) +{ + Extension ext; + int ret; + + memset(&ext, 0, sizeof(ext)); + + ext.critical = critical_flag; + ret = der_copy_oid(oid, &ext.extnID); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + ret = der_copy_octet_string(data, &ext.extnValue); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + ret = add_Extensions(tbsc->extensions, &ext); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } +out: + free_Extension(&ext); + return ret; +} + +static int +build_proxy_prefix(hx509_context context, const Name *issuer, Name *subject) +{ + char *tstr; + time_t t; + int ret; + + ret = copy_Name(issuer, subject); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to copy subject name"); + return ret; + } + + t = time(NULL); + ret = asprintf(&tstr, "ts-%lu", (unsigned long)t); + if (ret == -1 || tstr == NULL) { + hx509_set_error_string(context, 0, ENOMEM, + "Failed to copy subject name"); + return ENOMEM; + } + /* prefix with CN=<ts>,...*/ + ret = _hx509_name_modify(context, subject, 1, &asn1_oid_id_at_commonName, tstr); + free(tstr); + if (ret) + free_Name(subject); + return ret; +} + +static int +ca_sign(hx509_context context, + hx509_ca_tbs tbs, + hx509_private_key signer, + const AuthorityKeyIdentifier *ai, + const Name *issuername, + hx509_cert *certificate) +{ + heim_error_t error = NULL; + heim_octet_string data; + Certificate c; + TBSCertificate *tbsc; + size_t size; + int ret; + const AlgorithmIdentifier *sigalg; + time_t notBefore; + time_t notAfter; + + sigalg = tbs->sigalg; + if (sigalg == NULL) + sigalg = _hx509_crypto_default_sig_alg; + + memset(&c, 0, sizeof(c)); + + /* + * Default values are: Valid since 24h ago, valid one year into + * the future, KeyUsage digitalSignature and keyEncipherment set, + * and keyCertSign for CA certificates. + */ + notBefore = tbs->notBefore; + if (notBefore == 0) + notBefore = time(NULL) - 3600 * 24; + notAfter = tbs->notAfter; + if (notAfter == 0) + notAfter = time(NULL) + 3600 * 24 * 365; + + if (tbs->flags.ca) { + tbs->ku.keyCertSign = 1; + tbs->ku.cRLSign = 1; + } else if (KeyUsage2int(tbs->ku) == 0) { + tbs->ku.digitalSignature = 1; + tbs->ku.keyEncipherment = 1; + } + + /* + * + */ + + tbsc = &c.tbsCertificate; + + /* Default subject Name to empty */ + if (tbs->subject == NULL && + (ret = hx509_empty_name(context, &tbs->subject))) + return ret; + + /* Sanity checks */ + if (tbs->flags.key == 0) { + ret = EINVAL; + hx509_set_error_string(context, 0, ret, "No public key set"); + return ret; + } + /* + * Don't put restrictions on proxy certificate's subject name, it + * will be generated below. + */ + if (!tbs->flags.proxy) { + if (hx509_name_is_null_p(tbs->subject) && tbs->san.len == 0) { + hx509_set_error_string(context, 0, EINVAL, + "Empty subject and no SubjectAltNames"); + return EINVAL; + } + } + if (tbs->flags.ca && tbs->flags.proxy) { + hx509_set_error_string(context, 0, EINVAL, "Can't be proxy and CA " + "at the same time"); + return EINVAL; + } + if (tbs->flags.proxy) { + if (tbs->san.len > 0) { + hx509_set_error_string(context, 0, EINVAL, + "Proxy certificate is not allowed " + "to have SubjectAltNames"); + return EINVAL; + } + } + + /* version [0] Version OPTIONAL, -- EXPLICIT nnn DEFAULT 1, */ + tbsc->version = calloc(1, sizeof(*tbsc->version)); + if (tbsc->version == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + *tbsc->version = rfc3280_version_3; + /* serialNumber CertificateSerialNumber, */ + if (tbs->flags.serial) { + ret = der_copy_heim_integer(&tbs->serial, &tbsc->serialNumber); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + } else { + /* + * If no explicit serial number is specified, 20 random bytes should be + * sufficiently collision resistant. Since the serial number must be a + * positive integer, ensure minimal ASN.1 DER form by forcing the high + * bit off and the next bit on (thus avoiding an all zero first octet). + */ + tbsc->serialNumber.length = 20; + tbsc->serialNumber.data = malloc(tbsc->serialNumber.length); + if (tbsc->serialNumber.data == NULL){ + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + RAND_bytes(tbsc->serialNumber.data, tbsc->serialNumber.length); + ((unsigned char *)tbsc->serialNumber.data)[0] &= 0x7f; + ((unsigned char *)tbsc->serialNumber.data)[0] |= 0x40; + } + /* signature AlgorithmIdentifier, */ + ret = copy_AlgorithmIdentifier(sigalg, &tbsc->signature); + if (ret) { + hx509_set_error_string(context, 0, ret, "Failed to copy signature alg"); + goto out; + } + /* issuer Name, */ + if (issuername) + ret = copy_Name(issuername, &tbsc->issuer); + else + ret = hx509_name_to_Name(tbs->subject, &tbsc->issuer); + if (ret) { + hx509_set_error_string(context, 0, ret, "Failed to copy issuer name"); + goto out; + } + /* validity Validity, */ + { + /* + * From RFC 5280, section 4.1.2.5: + * + * CAs conforming to this profile MUST always encode certificate + * validity dates through the year 2049 as UTCTime; certificate validity + * dates in 2050 or later MUST be encoded as GeneralizedTime. + * Conforming applications MUST be able to process validity dates that + * are encoded in either UTCTime or GeneralizedTime. + * + * 2524608000 is seconds since the epoch for 2050-01-01T00:00:00Z. + * + * Both, ...u.generalTime and ...u..utcTime are time_t. + */ + if (notBefore < 1 || (int64_t)notBefore < 2524608000) + tbsc->validity.notBefore.element = choice_Time_utcTime; + else + tbsc->validity.notBefore.element = choice_Time_generalTime; + tbsc->validity.notBefore.u.generalTime = notBefore; + + if (notAfter < 1 || (int64_t)notAfter < 2524608000) + tbsc->validity.notAfter.element = choice_Time_utcTime; + else + tbsc->validity.notAfter.element = choice_Time_generalTime; + tbsc->validity.notAfter.u.generalTime = notAfter; + } + /* subject Name, */ + if (tbs->flags.proxy) { + ret = build_proxy_prefix(context, &tbsc->issuer, &tbsc->subject); + if (ret) + goto out; + } else { + ret = hx509_name_to_Name(tbs->subject, &tbsc->subject); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to copy subject name"); + goto out; + } + } + /* subjectPublicKeyInfo SubjectPublicKeyInfo, */ + ret = copy_SubjectPublicKeyInfo(&tbs->spki, &tbsc->subjectPublicKeyInfo); + if (ret) { + hx509_set_error_string(context, 0, ret, "Failed to copy spki"); + goto out; + } + /* issuerUniqueID [1] IMPLICIT BIT STRING OPTIONAL */ + if (tbs->issuerUniqueID.length) { + tbsc->issuerUniqueID = calloc(1, sizeof(*tbsc->issuerUniqueID)); + if (tbsc->issuerUniqueID == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + ret = der_copy_bit_string(&tbs->issuerUniqueID, tbsc->issuerUniqueID); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + } + /* subjectUniqueID [2] IMPLICIT BIT STRING OPTIONAL */ + if (tbs->subjectUniqueID.length) { + tbsc->subjectUniqueID = calloc(1, sizeof(*tbsc->subjectUniqueID)); + if (tbsc->subjectUniqueID == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + + ret = der_copy_bit_string(&tbs->subjectUniqueID, tbsc->subjectUniqueID); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + } + + /* extensions [3] EXPLICIT Extensions OPTIONAL */ + tbsc->extensions = calloc(1, sizeof(*tbsc->extensions)); + if (tbsc->extensions == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + + /* Add the text BMP string Domaincontroller to the cert */ + if (tbs->flags.domaincontroller) { + data.data = rk_UNCONST("\x1e\x20\x00\x44\x00\x6f\x00\x6d" + "\x00\x61\x00\x69\x00\x6e\x00\x43" + "\x00\x6f\x00\x6e\x00\x74\x00\x72" + "\x00\x6f\x00\x6c\x00\x6c\x00\x65" + "\x00\x72"); + data.length = 34; + + ret = add_extension(context, tbsc, 0, + &asn1_oid_id_ms_cert_enroll_domaincontroller, + &data); + if (ret) + goto out; + } + + /* Add KeyUsage */ + if (KeyUsage2int(tbs->ku) > 0) { + ASN1_MALLOC_ENCODE(KeyUsage, data.data, data.length, + &tbs->ku, &size, ret); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + if (size != data.length) + _hx509_abort("internal ASN.1 encoder error"); + ret = add_extension(context, tbsc, 1, + &asn1_oid_id_x509_ce_keyUsage, &data); + free(data.data); + if (ret) + goto out; + } + + /* Add ExtendedKeyUsage */ + if (tbs->eku.len > 0) { + ASN1_MALLOC_ENCODE(ExtKeyUsage, data.data, data.length, + &tbs->eku, &size, ret); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + if (size != data.length) + _hx509_abort("internal ASN.1 encoder error"); + ret = add_extension(context, tbsc, 1, + &asn1_oid_id_x509_ce_extKeyUsage, &data); + free(data.data); + if (ret) + goto out; + } + + /* Add Subject Alternative Name */ + if (tbs->san.len > 0) { + ASN1_MALLOC_ENCODE(GeneralNames, data.data, data.length, + &tbs->san, &size, ret); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + if (size != data.length) + _hx509_abort("internal ASN.1 encoder error"); + + /* The SAN extension is critical if the subject Name is empty */ + ret = add_extension(context, tbsc, hx509_name_is_null_p(tbs->subject), + &asn1_oid_id_x509_ce_subjectAltName, &data); + free(data.data); + if (ret) + goto out; + } + + /* Add Authority Key Identifier */ + if (ai) { + ASN1_MALLOC_ENCODE(AuthorityKeyIdentifier, data.data, data.length, + ai, &size, ret); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + if (size != data.length) + _hx509_abort("internal ASN.1 encoder error"); + ret = add_extension(context, tbsc, 0, + &asn1_oid_id_x509_ce_authorityKeyIdentifier, + &data); + free(data.data); + if (ret) + goto out; + } + + /* Add Subject Key Identifier */ + { + SubjectKeyIdentifier si; + unsigned char hash[SHA_DIGEST_LENGTH]; + + { + EVP_MD_CTX *ctx; + + ctx = EVP_MD_CTX_create(); + EVP_DigestInit_ex(ctx, EVP_sha1(), NULL); + EVP_DigestUpdate(ctx, tbs->spki.subjectPublicKey.data, + tbs->spki.subjectPublicKey.length / 8); + EVP_DigestFinal_ex(ctx, hash, NULL); + EVP_MD_CTX_destroy(ctx); + } + + si.data = hash; + si.length = sizeof(hash); + + ASN1_MALLOC_ENCODE(SubjectKeyIdentifier, data.data, data.length, + &si, &size, ret); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + if (size != data.length) + _hx509_abort("internal ASN.1 encoder error"); + ret = add_extension(context, tbsc, 0, + &asn1_oid_id_x509_ce_subjectKeyIdentifier, + &data); + free(data.data); + if (ret) + goto out; + } + + /* Add BasicConstraints */ + { + BasicConstraints bc; + unsigned int path; + + memset(&bc, 0, sizeof(bc)); + + if (tbs->flags.ca) { + bc.cA = 1; + if (tbs->pathLenConstraint >= 0) { + path = tbs->pathLenConstraint; + bc.pathLenConstraint = &path; + } + } + + ASN1_MALLOC_ENCODE(BasicConstraints, data.data, data.length, + &bc, &size, ret); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + if (size != data.length) + _hx509_abort("internal ASN.1 encoder error"); + /* Critical if this is a CA */ + ret = add_extension(context, tbsc, tbs->flags.ca, + &asn1_oid_id_x509_ce_basicConstraints, + &data); + free(data.data); + if (ret) + goto out; + } + + /* Add Proxy */ + if (tbs->flags.proxy) { + ProxyCertInfo info; + + memset(&info, 0, sizeof(info)); + + if (tbs->pathLenConstraint >= 0) { + info.pCPathLenConstraint = + malloc(sizeof(*info.pCPathLenConstraint)); + if (info.pCPathLenConstraint == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + *info.pCPathLenConstraint = tbs->pathLenConstraint; + } + + ret = der_copy_oid(&asn1_oid_id_pkix_ppl_inheritAll, + &info.proxyPolicy.policyLanguage); + if (ret) { + free_ProxyCertInfo(&info); + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + + ASN1_MALLOC_ENCODE(ProxyCertInfo, data.data, data.length, + &info, &size, ret); + free_ProxyCertInfo(&info); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + if (size != data.length) + _hx509_abort("internal ASN.1 encoder error"); + ret = add_extension(context, tbsc, 0, + &asn1_oid_id_pkix_pe_proxyCertInfo, + &data); + free(data.data); + if (ret) + goto out; + } + + /* Add CRL distribution point */ + if (tbs->crldp.len) { + ASN1_MALLOC_ENCODE(CRLDistributionPoints, data.data, data.length, + &tbs->crldp, &size, ret); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + if (size != data.length) + _hx509_abort("internal ASN.1 encoder error"); + ret = add_extension(context, tbsc, FALSE, + &asn1_oid_id_x509_ce_cRLDistributionPoints, + &data); + free(data.data); + if (ret) + goto out; + } + + /* Add CertificatePolicies */ + if (tbs->cps.len) { + ASN1_MALLOC_ENCODE(CertificatePolicies, data.data, data.length, + &tbs->cps, &size, ret); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + if (size != data.length) + _hx509_abort("internal ASN.1 encoder error"); + ret = add_extension(context, tbsc, FALSE, + &asn1_oid_id_x509_ce_certificatePolicies, &data); + free(data.data); + if (ret) + goto out; + } + + /* Add PolicyMappings */ + if (tbs->cps.len) { + ASN1_MALLOC_ENCODE(PolicyMappings, data.data, data.length, + &tbs->pms, &size, ret); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + if (size != data.length) + _hx509_abort("internal ASN.1 encoder error"); + ret = add_extension(context, tbsc, FALSE, + &asn1_oid_id_x509_ce_policyMappings, &data); + free(data.data); + if (ret) + goto out; + } + + /* Add Heimdal PKINIT ticket max life extension */ + if (tbs->pkinitTicketMaxLife > 0) { + ASN1_MALLOC_ENCODE(HeimPkinitPrincMaxLifeSecs, data.data, data.length, + &tbs->pkinitTicketMaxLife, &size, ret); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + if (size != data.length) + _hx509_abort("internal ASN.1 encoder error"); + ret = add_extension(context, tbsc, FALSE, + &asn1_oid_id_heim_ce_pkinit_princ_max_life, &data); + free(data.data); + if (ret) + goto out; + } + + ASN1_MALLOC_ENCODE(TBSCertificate, data.data, data.length,tbsc, &size, ret); + if (ret) { + hx509_set_error_string(context, 0, ret, "malloc out of memory"); + goto out; + } + if (data.length != size) + _hx509_abort("internal ASN.1 encoder error"); + + ret = _hx509_create_signature_bitstring(context, + signer, + sigalg, + &data, + &c.signatureAlgorithm, + &c.signatureValue); + free(data.data); + if (ret) + goto out; + + *certificate = hx509_cert_init(context, &c, &error); + if (*certificate == NULL) { + ret = heim_error_get_code(error); + heim_release(error); + goto out; + } + + free_Certificate(&c); + + return 0; + +out: + free_Certificate(&c); + return ret; +} + +static int +get_AuthorityKeyIdentifier(hx509_context context, + const Certificate *certificate, + AuthorityKeyIdentifier *ai) +{ + SubjectKeyIdentifier si; + int ret; + + ret = _hx509_find_extension_subject_key_id(certificate, &si); + if (ret == 0) { + ai->keyIdentifier = calloc(1, sizeof(*ai->keyIdentifier)); + if (ai->keyIdentifier == NULL) { + free_SubjectKeyIdentifier(&si); + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + ret = der_copy_octet_string(&si, ai->keyIdentifier); + free_SubjectKeyIdentifier(&si); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + } else { + GeneralNames gns; + GeneralName gn; + Name name; + + memset(&gn, 0, sizeof(gn)); + memset(&gns, 0, sizeof(gns)); + memset(&name, 0, sizeof(name)); + + ai->authorityCertIssuer = + calloc(1, sizeof(*ai->authorityCertIssuer)); + if (ai->authorityCertIssuer == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + ai->authorityCertSerialNumber = + calloc(1, sizeof(*ai->authorityCertSerialNumber)); + if (ai->authorityCertSerialNumber == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + + /* + * XXX unbreak when asn1 compiler handle IMPLICIT + * + * This is so horrible. + */ + + ret = copy_Name(&certificate->tbsCertificate.subject, &name); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + + memset(&gn, 0, sizeof(gn)); + gn.element = choice_GeneralName_directoryName; + gn.u.directoryName.element = choice_Name_rdnSequence; + gn.u.directoryName.u.rdnSequence = name.u.rdnSequence; + + ret = add_GeneralNames(&gns, &gn); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + + ai->authorityCertIssuer->val = gns.val; + ai->authorityCertIssuer->len = gns.len; + + ret = der_copy_heim_integer(&certificate->tbsCertificate.serialNumber, + ai->authorityCertSerialNumber); + if (ai->authorityCertSerialNumber == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + } +out: + if (ret) + free_AuthorityKeyIdentifier(ai); + return ret; +} + + +/** + * Sign a to-be-signed certificate object with a issuer certificate. + * + * The caller needs to at least have called the following functions on the + * to-be-signed certificate object: + * - hx509_ca_tbs_init() + * - hx509_ca_tbs_set_subject() + * - hx509_ca_tbs_set_spki() + * + * When done the to-be-signed certificate object should be freed with + * hx509_ca_tbs_free(). + * + * When creating self-signed certificate use hx509_ca_sign_self() instead. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param signer the CA certificate object to sign with (need private key). + * @param certificate return cerificate, free with hx509_cert_free(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_sign(hx509_context context, + hx509_ca_tbs tbs, + hx509_cert signer, + hx509_cert *certificate) +{ + const Certificate *signer_cert; + AuthorityKeyIdentifier ai; + int ret; + + memset(&ai, 0, sizeof(ai)); + + signer_cert = _hx509_get_cert(signer); + + ret = get_AuthorityKeyIdentifier(context, signer_cert, &ai); + if (ret) + goto out; + + ret = ca_sign(context, + tbs, + _hx509_cert_private_key(signer), + &ai, + &signer_cert->tbsCertificate.subject, + certificate); + +out: + free_AuthorityKeyIdentifier(&ai); + + return ret; +} + +/** + * Work just like hx509_ca_sign() but signs it-self. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param signer private key to sign with. + * @param certificate return cerificate, free with hx509_cert_free(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_sign_self(hx509_context context, + hx509_ca_tbs tbs, + hx509_private_key signer, + hx509_cert *certificate) +{ + return ca_sign(context, + tbs, + signer, + NULL, + NULL, + certificate); +} + +/* + * The following used to be `kdc_issue_certificate()', which was added for + * kx509 support in the kdc, then adapted for bx509d. It now has no + * kdc-specific code and very little krb5-specific code, and is named + * `hx509_ca_issue_certificate()'. + */ + +/* From lib/krb5/principal.c */ +#define princ_num_comp(P) ((P)->principalName.name_string.len) +#define princ_type(P) ((P)->principalName.name_type) +#define princ_comp(P) ((P)->principalName.name_string.val) +#define princ_ncomp(P, N) ((P)->principalName.name_string.val[(N)]) +#define princ_realm(P) ((P)->realm) + +static const char * +princ_get_comp_string(KRB5PrincipalName *principal, unsigned int component) +{ + if (component >= princ_num_comp(principal)) + return NULL; + return princ_ncomp(principal, component); +} +/* XXX Add unparse_name() */ + +typedef enum { + CERT_NOTSUP = 0, + CERT_CLIENT = 1, + CERT_SERVER = 2, + CERT_MIXED = 3 +} cert_type; + +static void +frees(char **s) +{ + free(*s); + *s = NULL; +} + +static heim_error_code +count_sans(hx509_request req, size_t *n) +{ + size_t i; + char *s = NULL; + int ret = 0; + + *n = 0; + for (i = 0; ret == 0; i++) { + hx509_san_type san_type; + + ret = hx509_request_get_san(req, i, &san_type, &s); + if (ret) + break; + switch (san_type) { + case HX509_SAN_TYPE_DNSNAME: + case HX509_SAN_TYPE_EMAIL: + case HX509_SAN_TYPE_XMPP: + case HX509_SAN_TYPE_PKINIT: + case HX509_SAN_TYPE_MS_UPN: + (*n)++; + break; + default: + ret = ENOTSUP; + } + frees(&s); + } + free(s); + return ret == HX509_NO_ITEM ? 0 : ret; +} + +static int +has_sans(hx509_request req) +{ + hx509_san_type san_type; + char *s = NULL; + int ret = hx509_request_get_san(req, 0, &san_type, &s); + + frees(&s); + return ret == HX509_NO_ITEM ? 0 : 1; +} + +static cert_type +characterize_cprinc(hx509_context context, + KRB5PrincipalName *cprinc) +{ + unsigned int ncomp = princ_num_comp(cprinc); + const char *comp1 = princ_get_comp_string(cprinc, 1); + + switch (ncomp) { + case 1: + return CERT_CLIENT; + case 2: + if (strchr(comp1, '.') == NULL) + return CERT_CLIENT; + return CERT_SERVER; + case 3: + if (strchr(comp1, '.')) + return CERT_SERVER; + return CERT_NOTSUP; + default: + return CERT_NOTSUP; + } +} + +/* Characterize request as client or server cert req */ +static cert_type +characterize(hx509_context context, + KRB5PrincipalName *cprinc, + hx509_request req) +{ + heim_error_code ret = 0; + cert_type res = CERT_NOTSUP; + size_t i; + char *s = NULL; + int want_ekus = 0; + + if (!has_sans(req)) + return characterize_cprinc(context, cprinc); + + for (i = 0; ret == 0; i++) { + heim_oid oid; + + frees(&s); + ret = hx509_request_get_eku(req, i, &s); + if (ret) + break; + + want_ekus = 1; + ret = der_parse_heim_oid(s, ".", &oid); + if (ret) + break; + /* + * If the client wants only a server certificate, then we'll be + * willing to issue one that may be longer-lived than the client's + * ticket/token. + * + * There may be other server EKUs, but these are the ones we know + * of. + */ + if (der_heim_oid_cmp(&asn1_oid_id_pkix_kp_serverAuth, &oid) && + der_heim_oid_cmp(&asn1_oid_id_pkix_kp_OCSPSigning, &oid) && + der_heim_oid_cmp(&asn1_oid_id_pkix_kp_secureShellServer, &oid)) + res |= CERT_CLIENT; + else + res |= CERT_SERVER; + der_free_oid(&oid); + } + frees(&s); + if (ret == HX509_NO_ITEM) + ret = 0; + + for (i = 0; ret == 0; i++) { + hx509_san_type san_type; + + frees(&s); + ret = hx509_request_get_san(req, i, &san_type, &s); + if (ret) + break; + switch (san_type) { + case HX509_SAN_TYPE_DNSNAME: + if (!want_ekus) + res |= CERT_SERVER; + break; + case HX509_SAN_TYPE_EMAIL: + case HX509_SAN_TYPE_XMPP: + case HX509_SAN_TYPE_PKINIT: + case HX509_SAN_TYPE_MS_UPN: + if (!want_ekus) + res |= CERT_CLIENT; + break; + default: + ret = ENOTSUP; + } + if (ret) + break; + } + frees(&s); + if (ret == HX509_NO_ITEM) + ret = 0; + return ret ? CERT_NOTSUP : res; +} + +/* + * Get a configuration sub-tree for kx509 based on what's being requested and + * by whom. + * + * We have a number of cases: + * + * - default certificate (no CSR used, or no certificate extensions requested) + * - for client principals + * - for service principals + * - client certificate requested (CSR used and client-y SANs/EKUs requested) + * - server certificate requested (CSR used and server-y SANs/EKUs requested) + * - mixed client/server certificate requested (...) + */ +static heim_error_code +get_cf(hx509_context context, + const heim_config_binding *cf, + heim_log_facility *logf, + hx509_request req, + KRB5PrincipalName *cprinc, + const heim_config_binding **out) +{ + heim_error_code ret; + unsigned int ncomp = princ_num_comp(cprinc); + const char *realm = princ_realm(cprinc); + const char *comp0 = princ_get_comp_string(cprinc, 0); + const char *comp1 = princ_get_comp_string(cprinc, 1); + const char *label = NULL; + const char *svc = NULL; + const char *def = NULL; + cert_type certtype = CERT_NOTSUP; + size_t nsans = 0; + + *out = NULL; + if (ncomp == 0) { + heim_log_msg(context->hcontext, logf, 5, NULL, + "Client principal has no components!"); + hx509_set_error_string(context, 0, ret = ENOTSUP, + "Client principal has no components!"); + return ret; + } + + if ((ret = count_sans(req, &nsans)) || + (certtype = characterize(context, cprinc, req)) == CERT_NOTSUP) { + heim_log_msg(context->hcontext, logf, 5, NULL, + "Could not characterize CSR"); + hx509_set_error_string(context, 0, ret, "Could not characterize CSR"); + return ret; + } + + if (nsans) { + def = "custom"; + /* Client requested some certificate extension, a SAN or EKU */ + switch (certtype) { + case CERT_MIXED: label = "mixed"; break; + case CERT_CLIENT: label = "client"; break; + case CERT_SERVER: label = "server"; break; + default: + hx509_set_error_string(context, 0, ret = ENOTSUP, + "Requested SAN/EKU combination not " + "supported"); + return ret; + } + } else { + def = "default"; + /* Default certificate desired */ + if (ncomp == 1) { + label = "user"; + } else if (ncomp == 2 && strcmp(comp1, "root") == 0) { + label = "root_user"; + } else if (ncomp == 2 && strcmp(comp1, "admin") == 0) { + label = "admin_user"; + } else if (strchr(comp1, '.')) { + label = "hostbased_service"; + svc = comp0; + } else { + label = "other"; + } + } + + *out = heim_config_get_list(context->hcontext, cf, label, svc, NULL); + if (*out) { + ret = 0; + } else { + heim_log_msg(context->hcontext, logf, 3, NULL, + "No configuration for %s %s certificate's realm " + "-> %s -> kx509 -> %s%s%s", def, label, realm, label, + svc ? " -> " : "", svc ? svc : ""); + hx509_set_error_string(context, 0, EACCES, + "No configuration for %s %s certificate's realm " + "-> %s -> kx509 -> %s%s%s", def, label, realm, label, + svc ? " -> " : "", svc ? svc : ""); + } + return ret; +} + + +/* + * Find and set a certificate template using a configuration sub-tree + * appropriate to the requesting principal. + * + * This allows for the specification of the following in configuration: + * + * - certificates as templates, with ${var} tokens in subjectName attribute + * values that will be expanded later + * - a plain string with ${var} tokens to use as the subjectName + * - EKUs + * - whether to include a PKINIT SAN + */ +static heim_error_code +set_template(hx509_context context, + heim_log_facility *logf, + const heim_config_binding *cf, + hx509_ca_tbs tbs) +{ + heim_error_code ret = 0; + const char *cert_template = NULL; + const char *subj_name = NULL; + char **ekus = NULL; + + if (cf == NULL) + return EACCES; /* Can't happen */ + + cert_template = heim_config_get_string(context->hcontext, cf, + "template_cert", NULL); + subj_name = heim_config_get_string(context->hcontext, cf, "subject_name", + NULL); + ekus = heim_config_get_strings(context->hcontext, cf, "ekus", NULL); + + if (cert_template) { + hx509_certs certs; + hx509_cert template; + + ret = hx509_certs_init(context, cert_template, 0, NULL, &certs); + if (ret == 0) + ret = hx509_get_one_cert(context, certs, &template); + hx509_certs_free(&certs); + if (ret) { + heim_log_msg(context->hcontext, logf, 1, NULL, + "Failed to load certificate template from %s", + cert_template); + hx509_set_error_string(context, 0, EACCES, + "Failed to load certificate template from " + "%s", cert_template); + return ret; + } + + /* + * Only take the subjectName, the keyUsage, and EKUs from the template + * certificate. + */ + ret = hx509_ca_tbs_set_template(context, tbs, + HX509_CA_TEMPLATE_SUBJECT | + HX509_CA_TEMPLATE_KU | + HX509_CA_TEMPLATE_EKU, + template); + hx509_cert_free(template); + if (ret) + return ret; + } + + if (subj_name) { + hx509_name dn = NULL; + + ret = hx509_parse_name(context, subj_name, &dn); + if (ret == 0) + ret = hx509_ca_tbs_set_subject(context, tbs, dn); + hx509_name_free(&dn); + if (ret) + return ret; + } + + if (cert_template == NULL && subj_name == NULL) { + hx509_name dn = NULL; + + ret = hx509_empty_name(context, &dn); + if (ret == 0) + ret = hx509_ca_tbs_set_subject(context, tbs, dn); + hx509_name_free(&dn); + if (ret) + return ret; + } + + if (ekus) { + size_t i; + + for (i = 0; ret == 0 && ekus[i]; i++) { + heim_oid oid = { 0, 0 }; + + if ((ret = der_find_or_parse_heim_oid(ekus[i], ".", &oid)) == 0) + ret = hx509_ca_tbs_add_eku(context, tbs, &oid); + der_free_oid(&oid); + } + heim_config_free_strings(ekus); + } + + /* + * XXX A KeyUsage template would be nice, but it needs some smarts to + * remove, e.g., encipherOnly, decipherOnly, keyEncipherment, if the SPKI + * algorithm does not support encryption. The same logic should be added + * to hx509_ca_tbs_set_template()'s HX509_CA_TEMPLATE_KU functionality. + */ + return ret; +} + +/* + * Find and set a certificate template, set "variables" in `env', and add add + * default SANs/EKUs as appropriate. + * + * TODO: + * - lookup a template for the client principal in its HDB entry + * - lookup subjectName, SANs for a principal in its HDB entry + * - lookup a host-based client principal's HDB entry and add its canonical + * name / aliases as dNSName SANs + * (this would have to be if requested by the client, perhaps) + */ +static heim_error_code +set_tbs(hx509_context context, + heim_log_facility *logf, + const heim_config_binding *cf, + hx509_request req, + KRB5PrincipalName *cprinc, + hx509_env *env, + hx509_ca_tbs tbs) +{ + KRB5PrincipalName cprinc_no_realm = *cprinc; + heim_error_code ret; + unsigned int ncomp = princ_num_comp(cprinc); + const char *realm = princ_realm(cprinc); + const char *comp0 = princ_get_comp_string(cprinc, 0); + const char *comp1 = princ_get_comp_string(cprinc, 1); + const char *comp2 = princ_get_comp_string(cprinc, 2); + struct rk_strpool *strpool; + char *princ_no_realm = NULL; + char *princ = NULL; + + strpool = _hx509_unparse_kerberos_name(NULL, cprinc); + if (strpool) + princ = rk_strpoolcollect(strpool); + cprinc_no_realm.realm = NULL; + strpool = _hx509_unparse_kerberos_name(NULL, &cprinc_no_realm); + if (strpool) + princ_no_realm = rk_strpoolcollect(strpool); + if (princ == NULL || princ_no_realm == NULL) { + free(princ); + return hx509_enomem(context); + } + strpool = NULL; + ret = hx509_env_add(context, env, "principal-name-without-realm", + princ_no_realm); + if (ret == 0) + ret = hx509_env_add(context, env, "principal-name", princ); + if (ret == 0) + ret = hx509_env_add(context, env, "principal-name-realm", + realm); + + /* Populate requested certificate extensions from CSR/CSRPlus if allowed */ + if (ret == 0) + ret = hx509_ca_tbs_set_from_csr(context, tbs, req); + if (ret == 0) + ret = set_template(context, logf, cf, tbs); + + /* + * Optionally add PKINIT SAN. + * + * Adding an id-pkinit-san means the client can use the certificate to + * initiate PKINIT. That might seem odd, but it enables a sort of PKIX + * credential delegation by allowing forwarded Kerberos tickets to be + * used to acquire PKIX credentials. Thus this can work: + * + * PKIX (w/ HW token) -> Kerberos -> + * PKIX (w/ softtoken) -> Kerberos -> + * PKIX (w/ softtoken) -> Kerberos -> + * ... + * + * Note that we may not have added the PKINIT EKU -- that depends on the + * template, and host-based service templates might well not include it. + */ + if (ret == 0 && !has_sans(req) && + heim_config_get_bool_default(context->hcontext, cf, FALSE, + "include_pkinit_san", NULL)) { + ret = hx509_ca_tbs_add_san_pkinit(context, tbs, princ); + } + + if (ret) + goto out; + + if (ncomp == 1) { + const char *email_domain; + + ret = hx509_env_add(context, env, "principal-component0", + princ_no_realm); + + /* + * If configured, include an rfc822Name that's just the client's + * principal name sans realm @ configured email domain. + */ + if (ret == 0 && !has_sans(req) && + (email_domain = heim_config_get_string(context->hcontext, cf, + "email_domain", NULL))) { + char *email; + + if (asprintf(&email, "%s@%s", princ_no_realm, email_domain) == -1 || + email == NULL) + goto enomem; + ret = hx509_ca_tbs_add_san_rfc822name(context, tbs, email); + free(email); + } + } else if (ncomp == 2 || ncomp == 3) { + /* + * 2- and 3-component principal name. + * + * We do not have a reliable name-type indicator. If the second + * component has a '.' in it then we'll assume that the name is a + * host-based (2-component) or domain-based (3-component) service + * principal name. Else we'll assume it's a two-component admin-style + * username. + */ + + ret = hx509_env_add(context, env, "principal-component0", comp0); + if (ret == 0) + ret = hx509_env_add(context, env, "principal-component1", comp1); + if (ret == 0 && ncomp == 3) + ret = hx509_env_add(context, env, "principal-component2", comp2); + if (ret == 0 && strchr(comp1, '.')) { + /* Looks like host-based or domain-based service */ + ret = hx509_env_add(context, env, "principal-service-name", comp0); + if (ret == 0) + ret = hx509_env_add(context, env, "principal-host-name", + comp1); + if (ret == 0 && ncomp == 3) + ret = hx509_env_add(context, env, "principal-domain-name", + comp2); + if (ret == 0 && !has_sans(req) && + heim_config_get_bool_default(context->hcontext, cf, FALSE, + "include_dnsname_san", NULL)) { + ret = hx509_ca_tbs_add_san_hostname(context, tbs, comp1); + } + } + } else { + heim_log_msg(context->hcontext, logf, 5, NULL, + "kx509/bx509 client %s has too many components!", princ); + hx509_set_error_string(context, 0, ret = EACCES, + "kx509/bx509 client %s has too many " + "components!", princ); + } + +out: + if (ret == ENOMEM) + goto enomem; + free(princ_no_realm); + free(princ); + return ret; + +enomem: + heim_log_msg(context->hcontext, logf, 0, NULL, + "Could not set up TBSCertificate: Out of memory"); + ret = hx509_enomem(context); + goto out; +} + +/* + * Set the notBefore/notAfter for the certificate to be issued. + * + * Here `starttime' is the supplicant's credentials' notBefore equivalent, + * while `endtime' is the supplicant's credentials' notAfter equivalent. + * + * `req_life' is the lifetime requested by the supplicant. + * + * `endtime' must be larger than the current time. + * + * `starttime' can be zero or negative, in which case the notBefore will be the + * current time minus five minutes. + * + * `endtime', `req_life' and configuration parameters will be used to compute + * the actual notAfter. + */ +static heim_error_code +tbs_set_times(hx509_context context, + const heim_config_binding *cf, + heim_log_facility *logf, + time_t starttime, + time_t endtime, + time_t req_life, + hx509_ca_tbs tbs) +{ + time_t now = time(NULL); + time_t force = heim_config_get_time_default(context->hcontext, + cf, 5 * 24 * 3600, + "force_cert_lifetime", NULL); + time_t clamp = heim_config_get_time_default(context->hcontext, cf, 0, + "max_cert_lifetime", NULL); + int allow_more = heim_config_get_bool_default(context->hcontext, cf, FALSE, + "allow_extra_lifetime", + NULL); + starttime = starttime > 0 ? starttime : now - 5 * 60; + + if (endtime < now) { + heim_log_msg(context->hcontext, logf, 3, NULL, + "Endtime is in the past"); + hx509_set_error_string(context, 0, ERANGE, "Endtime is in the past"); + return ERANGE; + } + + /* Apply requested lifetime if shorter or if allowed more */ + if (req_life > 0 && req_life <= endtime - now) + endtime = now + req_life; + else if (req_life > 0 && allow_more) + endtime = now + req_life; + + /* Apply floor */ + if (force > 0 && force > endtime - now) + endtime = now + force; + + /* Apply ceiling */ + if (clamp > 0 && clamp < endtime - now) + endtime = now + clamp; + + hx509_ca_tbs_set_notAfter(context, tbs, endtime); + hx509_ca_tbs_set_notBefore(context, tbs, starttime); + return 0; +} + +/* + * Build a certifate for `principal' and its CSR. + * + * XXX Make `cprinc' a GeneralName! That's why this is private for now. + */ +heim_error_code +_hx509_ca_issue_certificate(hx509_context context, + const heim_config_binding *cf, + heim_log_facility *logf, + hx509_request req, + KRB5PrincipalName *cprinc, + time_t starttime, + time_t endtime, + time_t req_life, + int send_chain, + hx509_certs *out) +{ + heim_error_code ret; + const char *ca; + hx509_ca_tbs tbs = NULL; + hx509_certs chain = NULL; + hx509_cert signer = NULL; + hx509_cert cert = NULL; + hx509_env env = NULL; + KeyUsage ku; + + *out = NULL; + /* Force KU */ + ku = int2KeyUsage(0); + ku.digitalSignature = 1; + hx509_request_authorize_ku(req, ku); + + ret = get_cf(context, cf, logf, req, cprinc, &cf); + if (ret) + return ret; + + if ((ca = heim_config_get_string(context->hcontext, cf, + "ca", NULL)) == NULL) { + heim_log_msg(context->hcontext, logf, 3, NULL, + "No kx509 CA issuer credential specified"); + hx509_set_error_string(context, 0, ret = EACCES, + "No kx509 CA issuer credential specified"); + return ret; + } + + ret = hx509_ca_tbs_init(context, &tbs); + if (ret) { + heim_log_msg(context->hcontext, logf, 0, NULL, + "Failed to create certificate: Out of memory"); + return ret; + } + + /* Lookup a template and set things in `env' and `tbs' as appropriate */ + if (ret == 0) + ret = set_tbs(context, logf, cf, req, cprinc, &env, tbs); + + /* Populate generic template "env" variables */ + + /* + * The `tbs' and `env' are now complete as to naming and EKUs. + * + * We check that the `tbs' is not name-less, after which all remaining + * failures here will not be policy failures. So we also log the intent to + * issue a certificate now. + */ + if (ret == 0 && hx509_name_is_null_p(hx509_ca_tbs_get_name(tbs)) && + !has_sans(req)) { + heim_log_msg(context->hcontext, logf, 3, NULL, + "Not issuing certificate because it would have no names"); + hx509_set_error_string(context, 0, ret = EACCES, + "Not issuing certificate because it " + "would have no names"); + } + if (ret) + goto out; + + /* + * Still to be done below: + * + * - set certificate spki + * - set certificate validity + * - expand variables in certificate subject name template + * - sign certificate + * - encode certificate and chain + */ + + /* Load the issuer certificate and private key */ + { + hx509_certs certs; + hx509_query *q; + + ret = hx509_certs_init(context, ca, 0, NULL, &certs); + if (ret) { + heim_log_msg(context->hcontext, logf, 1, NULL, + "Failed to load CA certificate and private key %s", + ca); + hx509_set_error_string(context, 0, ret, "Failed to load " + "CA certificate and private key %s", ca); + goto out; + } + ret = hx509_query_alloc(context, &q); + if (ret) { + hx509_certs_free(&certs); + goto out; + } + + hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); + hx509_query_match_option(q, HX509_QUERY_OPTION_KU_KEYCERTSIGN); + + ret = hx509_certs_find(context, certs, q, &signer); + hx509_query_free(context, q); + hx509_certs_free(&certs); + if (ret) { + heim_log_msg(context->hcontext, logf, 1, NULL, + "Failed to find a CA certificate in %s", ca); + hx509_set_error_string(context, 0, ret, + "Failed to find a CA certificate in %s", + ca); + goto out; + } + } + + /* Populate the subject public key in the TBS context */ + { + SubjectPublicKeyInfo spki; + + ret = hx509_request_get_SubjectPublicKeyInfo(context, + req, &spki); + if (ret == 0) + ret = hx509_ca_tbs_set_spki(context, tbs, &spki); + free_SubjectPublicKeyInfo(&spki); + if (ret) + goto out; + } + + /* Work out cert expiration */ + if (ret == 0) + ret = tbs_set_times(context, cf, logf, starttime, endtime, req_life, + tbs); + + /* Expand the subjectName template in the TBS using the env */ + if (ret == 0) + ret = hx509_ca_tbs_subject_expand(context, tbs, env); + hx509_env_free(&env); + + /* All done with the TBS, sign/issue the certificate */ + if (ret == 0) + ret = hx509_ca_sign(context, tbs, signer, &cert); + + /* + * Gather the certificate and chain into a MEMORY store, being careful not + * to include private keys in the chain. + * + * We could have specified a separate configuration parameter for an hx509 + * store meant to have only the chain and no private keys, but expecting + * the full chain in the issuer credential store and copying only the certs + * (but not the private keys) is safer and easier to configure. + */ + if (ret == 0) + ret = hx509_certs_init(context, "MEMORY:certs", + HX509_CERTS_NO_PRIVATE_KEYS, NULL, out); + if (ret == 0) + ret = hx509_certs_add(context, *out, cert); + if (ret == 0 && send_chain) { + ret = hx509_certs_init(context, ca, + HX509_CERTS_NO_PRIVATE_KEYS, NULL, &chain); + if (ret == 0) + ret = hx509_certs_merge(context, *out, chain); + } + +out: + hx509_certs_free(&chain); + if (env) + hx509_env_free(&env); + if (tbs) + hx509_ca_tbs_free(&tbs); + if (cert) + hx509_cert_free(cert); + if (signer) + hx509_cert_free(signer); + if (ret) + hx509_certs_free(out); + return ret; +} diff --git a/third_party/heimdal/lib/hx509/cert.c b/third_party/heimdal/lib/hx509/cert.c new file mode 100644 index 0000000..33805b8 --- /dev/null +++ b/third_party/heimdal/lib/hx509/cert.c @@ -0,0 +1,3892 @@ +/* + * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" +#include "crypto-headers.h" +#include <rtbl.h> + +/** + * @page page_cert The basic certificate + * + * The basic hx509 cerificate object in hx509 is hx509_cert. The + * hx509_cert object is representing one X509/PKIX certificate and + * associated attributes; like private key, friendly name, etc. + * + * A hx509_cert object is usully found via the keyset interfaces (@ref + * page_keyset), but its also possible to create a certificate + * directly from a parsed object with hx509_cert_init() and + * hx509_cert_init_data(). + * + * See the library functions here: @ref hx509_cert + */ + +struct hx509_verify_ctx_data { + hx509_certs trust_anchors; + int flags; +#define HX509_VERIFY_CTX_F_TIME_SET 1 +#define HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE 2 +#define HX509_VERIFY_CTX_F_REQUIRE_RFC3280 4 +#define HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS 8 +#define HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS 16 +#define HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK 32 + time_t time_now; + unsigned int max_depth; +#define HX509_VERIFY_MAX_DEPTH 30 + hx509_revoke_ctx revoke_ctx; +}; + +#define REQUIRE_RFC3280(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_REQUIRE_RFC3280) +#define CHECK_TA(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS) +#define ALLOW_DEF_TA(ctx) (((ctx)->flags & HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS) == 0) + +struct _hx509_cert_attrs { + size_t len; + hx509_cert_attribute *val; +}; + +struct hx509_cert_data { + unsigned int ref; + char *friendlyname; + Certificate *data; + hx509_private_key private_key; + struct _hx509_cert_attrs attrs; + hx509_name basename; + _hx509_cert_release_func release; + void *ctx; +}; + +typedef struct hx509_name_constraints { + NameConstraints *val; + size_t len; +} hx509_name_constraints; + +#define GeneralSubtrees_SET(g,var) \ + (g)->len = (var)->len, (g)->val = (var)->val; + +static void +init_context_once(void *ignored) +{ + + ENGINE_add_conf_module(); + OpenSSL_add_all_algorithms(); +} + +/** + * Return a cookie identifying this instance of a library. + * + * Inputs: + * + * @context A krb5_context + * @module Our library name or a library we depend on + * + * Outputs: The instance cookie + * + * @ingroup krb5_support + */ + +HX509_LIB_FUNCTION uintptr_t HX509_LIB_CALL +hx509_get_instance(const char *libname) +{ + static const char *instance = "libhx509"; + + if (strcmp(libname, "hx509") == 0) + return (uintptr_t)instance; + + return 0; +} + +#ifndef PATH_SEP +# define PATH_SEP ":" +#endif +static const char *hx509_config_file = +"~/.hx509/config" PATH_SEP +SYSCONFDIR "/hx509.conf" PATH_SEP +#ifdef _WIN32 +"%{COMMON_APPDATA}/Heimdal/hx509.conf" PATH_SEP +"%{WINDOWS}/hx509.ini" +#else /* _WIN32 */ +"/etc/hx509.conf" +#endif /* _WIN32 */ +; + +/** + * Creates a hx509 context that most functions in the library + * uses. The context is only allowed to be used by one thread at each + * moment. Free the context with hx509_context_free(). + * + * @param context Returns a pointer to new hx509 context. + * + * @return Returns an hx509 error code. + * + * @ingroup hx509 + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_context_init(hx509_context *contextp) +{ + static heim_base_once_t init_context = HEIM_BASE_ONCE_INIT; + heim_error_code ret; + hx509_context context; + const char *anchors; + char **files = NULL; + + *contextp = NULL; + context = calloc(1, sizeof(*context)); + if (context == NULL) + return ENOMEM; + + heim_base_once_f(&init_context, NULL, init_context_once); + + if ((context->hcontext = heim_context_init()) == NULL) { + free(context); + return ENOMEM; + } + + if ((ret = heim_get_default_config_files(hx509_config_file, + "HX509_CONFIG", + &files))) { + heim_context_free(&context->hcontext); + free(context); + return ret; + } + + /* If there's no hx509 config, we continue, as we never needed it before */ + if (files) + (void) heim_set_config_files(context->hcontext, files, &context->cf); + heim_free_config_files(files); + + _hx509_ks_null_register(context); + _hx509_ks_mem_register(context); + _hx509_ks_file_register(context); + _hx509_ks_pkcs12_register(context); + _hx509_ks_pkcs11_register(context); + _hx509_ks_dir_register(context); + _hx509_ks_keychain_register(context); + + context->ocsp_time_diff = + heim_config_get_time_default(context->hcontext, context->cf, + HX509_DEFAULT_OCSP_TIME_DIFF, + "libdefaults", "ocsp_time_dif", NULL); + + initialize_hx_error_table_r(&context->et_list); + initialize_asn1_error_table_r(&context->et_list); + +#ifdef HX509_DEFAULT_ANCHORS + anchors = heim_config_get_string_default(context->hcontext, context->cf, + HX509_DEFAULT_ANCHORS, + "libdefaults", "anchors", NULL); +#else + anchors = heim_config_get_string(context->hcontext, context->cf, + "libdefaults", "anchors", NULL); +#endif + if (anchors) + (void)hx509_certs_init(context, anchors, 0, NULL, + &context->default_trust_anchors); + + *contextp = context; + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_set_log_dest(hx509_context context, heim_log_facility *fac) +{ + return heim_set_log_dest(context->hcontext, fac); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_set_debug_dest(hx509_context context, heim_log_facility *fac) +{ + return heim_set_debug_dest(context->hcontext, fac); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_set_warn_dest(hx509_context context, heim_log_facility *fac) +{ + return heim_set_warn_dest(context->hcontext, fac); +} + +/** + * Selects if the hx509_revoke_verify() function is going to require + * the existans of a revokation method (OCSP, CRL) or not. Note that + * hx509_verify_path(), hx509_cms_verify_signed(), and other function + * call hx509_revoke_verify(). + * + * @param context hx509 context to change the flag for. + * @param flag zero, revokation method required, non zero missing + * revokation method ok + * + * @ingroup hx509_verify + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_context_set_missing_revoke(hx509_context context, int flag) +{ + if (flag) + context->flags |= HX509_CTX_VERIFY_MISSING_OK; + else + context->flags &= ~HX509_CTX_VERIFY_MISSING_OK; +} + +/** + * Free the context allocated by hx509_context_init(). + * + * @param context context to be freed. + * + * @ingroup hx509 + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_context_free(hx509_context *context) +{ + if (!*context) + return; + + hx509_clear_error_string(*context); + if ((*context)->ks_ops) { + free((*context)->ks_ops); + (*context)->ks_ops = NULL; + } + (*context)->ks_num_ops = 0; + free_error_table ((*context)->et_list); + if ((*context)->querystat) + free((*context)->querystat); + hx509_certs_free(&(*context)->default_trust_anchors); + heim_config_file_free((*context)->hcontext, (*context)->cf); + heim_context_free(&(*context)->hcontext); + memset(*context, 0, sizeof(**context)); + free(*context); + *context = NULL; +} + +/* + * + */ + +HX509_LIB_FUNCTION Certificate * HX509_LIB_CALL +_hx509_get_cert(hx509_cert cert) +{ + return cert->data; +} + +/* + * + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_cert_get_version(const Certificate *t) +{ + return t->tbsCertificate.version ? *t->tbsCertificate.version + 1 : 1; +} + +static hx509_cert +cert_init(hx509_context context, heim_error_t *error) +{ + hx509_cert cert; + + cert = malloc(sizeof(*cert)); + if (cert == NULL) { + if (error) + *error = heim_error_create_enomem(); + return NULL; + } + cert->ref = 1; + cert->friendlyname = NULL; + cert->attrs.len = 0; + cert->attrs.val = NULL; + cert->private_key = NULL; + cert->basename = NULL; + cert->release = NULL; + cert->ctx = NULL; + cert->data= NULL; + return cert; +} + +/** + * Allocate and init an hx509 certificate object from the decoded + * certificate `c´. + * + * @param context A hx509 context. + * @param c + * @param error + * + * @return Returns an hx509 certificate + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION hx509_cert HX509_LIB_CALL +hx509_cert_init(hx509_context context, const Certificate *c, heim_error_t *error) +{ + hx509_cert cert; + int ret; + + if ((cert = cert_init(context, error)) == NULL) + return NULL; + + cert->data = calloc(1, sizeof(*(cert->data))); + if (cert->data == NULL) { + free(cert); + if (error) + *error = heim_error_create_enomem(); + return NULL; + } + ret = copy_Certificate(c, cert->data); + if (ret) { + free(cert->data); + free(cert); + cert = NULL; + } + return cert; +} + +/** + * Copy a certificate object, but drop any private key assignment. + * + * @param context A hx509 context. + * @param src Certificate object + * @param error + * + * @return Returns an hx509 certificate + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION hx509_cert HX509_LIB_CALL +hx509_cert_copy_no_private_key(hx509_context context, + hx509_cert src, + heim_error_t *error) +{ + return hx509_cert_init(context, src->data, error); +} + +/** + * Allocate and init an hx509 certificate object containing only a private key + * (but no Certificate). + * + * @param context A hx509 context. + * @param key + * @param error + * + * @return Returns an hx509 certificate + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION hx509_cert HX509_LIB_CALL +hx509_cert_init_private_key(hx509_context context, + hx509_private_key key, + heim_error_t *error) +{ + hx509_cert cert; + + if ((cert = cert_init(context, error))) + (void) _hx509_cert_assign_key(cert, key); + return cert; +} + +/** + * Just like hx509_cert_init(), but instead of a decode certificate + * takes an pointer and length to a memory region that contains a + * DER/BER encoded certificate. + * + * If the memory region doesn't contain just the certificate and + * nothing more the function will fail with + * HX509_EXTRA_DATA_AFTER_STRUCTURE. + * + * @param context A hx509 context. + * @param ptr pointer to memory region containing encoded certificate. + * @param len length of memory region. + * @param error possibly returns an error + * + * @return An hx509 certificate + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION hx509_cert HX509_LIB_CALL +hx509_cert_init_data(hx509_context context, + const void *ptr, + size_t len, + heim_error_t *error) +{ + hx509_cert cert; + Certificate t; + size_t size; + int ret; + + ret = decode_Certificate(ptr, len, &t, &size); + if (ret) { + if (error) + *error = heim_error_create(ret, "Failed to decode certificate"); + errno = ret; + return NULL; + } + if (size != len) { + free_Certificate(&t); + if (error) + *error = heim_error_create(HX509_EXTRA_DATA_AFTER_STRUCTURE, + "Extra data after certificate"); + errno = HX509_EXTRA_DATA_AFTER_STRUCTURE; + return NULL; + } + + cert = hx509_cert_init(context, &t, error); + free_Certificate(&t); + return cert; +} + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_cert_set_release(hx509_cert cert, + _hx509_cert_release_func release, + void *ctx) +{ + cert->release = release; + cert->ctx = ctx; +} + + +/* Doesn't make a copy of `private_key'. */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_cert_assign_key(hx509_cert cert, hx509_private_key private_key) +{ + if (cert->private_key) + hx509_private_key_free(&cert->private_key); + cert->private_key = _hx509_private_key_ref(private_key); + return 0; +} + +/** + * Free reference to the hx509 certificate object, if the refcounter + * reaches 0, the object if freed. Its allowed to pass in NULL. + * + * @param cert the cert to free. + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_cert_free(hx509_cert cert) +{ + size_t i; + + if (cert == NULL) + return; + + if (cert->ref <= 0) + _hx509_abort("cert refcount <= 0 on free"); + if (--cert->ref > 0) + return; + + if (cert->release) + (cert->release)(cert, cert->ctx); + + if (cert->private_key) + hx509_private_key_free(&cert->private_key); + + if (cert->data) + free_Certificate(cert->data); + free(cert->data); + + for (i = 0; i < cert->attrs.len; i++) { + der_free_octet_string(&cert->attrs.val[i]->data); + der_free_oid(&cert->attrs.val[i]->oid); + free(cert->attrs.val[i]); + } + free(cert->attrs.val); + free(cert->friendlyname); + if (cert->basename) + hx509_name_free(&cert->basename); + memset(cert, 0, sizeof(*cert)); + free(cert); +} + +/** + * Add a reference to a hx509 certificate object. + * + * @param cert a pointer to an hx509 certificate object. + * + * @return the same object as is passed in. + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION hx509_cert HX509_LIB_CALL +hx509_cert_ref(hx509_cert cert) +{ + if (cert == NULL) + return NULL; + if (cert->ref <= 0) + _hx509_abort("cert refcount <= 0"); + cert->ref++; + if (cert->ref == 0) + _hx509_abort("cert refcount == 0"); + return cert; +} + +/** + * Allocate an verification context that is used fo control the + * verification process. + * + * @param context A hx509 context. + * @param ctx returns a pointer to a hx509_verify_ctx object. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_verify + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_verify_init_ctx(hx509_context context, hx509_verify_ctx *ctx) +{ + hx509_verify_ctx c; + + c = calloc(1, sizeof(*c)); + if (c == NULL) + return ENOMEM; + + c->max_depth = HX509_VERIFY_MAX_DEPTH; + + *ctx = c; + + return 0; +} + +/** + * Free an hx509 verification context. + * + * @param ctx the context to be freed. + * + * @ingroup hx509_verify + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_verify_destroy_ctx(hx509_verify_ctx ctx) +{ + if (ctx) { + hx509_certs_free(&ctx->trust_anchors); + hx509_revoke_free(&ctx->revoke_ctx); + memset(ctx, 0, sizeof(*ctx)); + } + free(ctx); +} + +/** + * Set the trust anchors in the verification context, makes an + * reference to the keyset, so the consumer can free the keyset + * independent of the destruction of the verification context (ctx). + * If there already is a keyset attached, it's released. + * + * @param ctx a verification context + * @param set a keyset containing the trust anchors. + * + * @ingroup hx509_verify + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_verify_attach_anchors(hx509_verify_ctx ctx, hx509_certs set) +{ + if (ctx->trust_anchors) + hx509_certs_free(&ctx->trust_anchors); + ctx->trust_anchors = hx509_certs_ref(set); +} + +/** + * Attach an revocation context to the verfication context, , makes an + * reference to the revoke context, so the consumer can free the + * revoke context independent of the destruction of the verification + * context. If there is no revoke context, the verification process is + * NOT going to check any verification status. + * + * @param ctx a verification context. + * @param revoke_ctx a revoke context. + * + * @ingroup hx509_verify + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_verify_attach_revoke(hx509_verify_ctx ctx, hx509_revoke_ctx revoke_ctx) +{ + if (ctx->revoke_ctx) + hx509_revoke_free(&ctx->revoke_ctx); + ctx->revoke_ctx = _hx509_revoke_ref(revoke_ctx); +} + +/** + * Set the clock time the the verification process is going to + * use. Used to check certificate in the past and future time. If not + * set the current time will be used. + * + * @param ctx a verification context. + * @param t the time the verifiation is using. + * + * + * @ingroup hx509_verify + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_verify_set_time(hx509_verify_ctx ctx, time_t t) +{ + ctx->flags |= HX509_VERIFY_CTX_F_TIME_SET; + ctx->time_now = t; +} + +HX509_LIB_FUNCTION time_t HX509_LIB_CALL +_hx509_verify_get_time(hx509_verify_ctx ctx) +{ + return ctx->time_now; +} + +/** + * Set the maximum depth of the certificate chain that the path + * builder is going to try. + * + * @param ctx a verification context + * @param max_depth maxium depth of the certificate chain, include + * trust anchor. + * + * @ingroup hx509_verify + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_verify_set_max_depth(hx509_verify_ctx ctx, unsigned int max_depth) +{ + ctx->max_depth = max_depth; +} + +/** + * Allow or deny the use of proxy certificates + * + * @param ctx a verification context + * @param boolean if non zero, allow proxy certificates. + * + * @ingroup hx509_verify + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx, int boolean) +{ + if (boolean) + ctx->flags |= HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE; + else + ctx->flags &= ~HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE; +} + +/** + * Select strict RFC3280 verification of certificiates. This means + * checking key usage on CA certificates, this will make version 1 + * certificiates unuseable. + * + * @param ctx a verification context + * @param boolean if non zero, use strict verification. + * + * @ingroup hx509_verify + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx, int boolean) +{ + if (boolean) + ctx->flags |= HX509_VERIFY_CTX_F_REQUIRE_RFC3280; + else + ctx->flags &= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280; +} + +/** + * Allow using the operating system builtin trust anchors if no other + * trust anchors are configured. + * + * @param ctx a verification context + * @param boolean if non zero, useing the operating systems builtin + * trust anchors. + * + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx, int boolean) +{ + if (boolean) + ctx->flags &= ~HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS; + else + ctx->flags |= HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS; +} + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_verify_ctx_f_allow_best_before_signature_algs(hx509_context ctx, + int boolean) +{ + if (boolean) + ctx->flags &= ~HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK; + else + ctx->flags |= HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK; +} + +static const Extension * +find_extension(const Certificate *cert, const heim_oid *oid, size_t *idx) +{ + const TBSCertificate *c = &cert->tbsCertificate; + + if (c->version == NULL || *c->version < 2 || c->extensions == NULL) + return NULL; + + for (;*idx < c->extensions->len; (*idx)++) { + if (der_heim_oid_cmp(&c->extensions->val[*idx].extnID, oid) == 0) + return &c->extensions->val[(*idx)++]; + } + return NULL; +} + +static int +find_extension_auth_key_id(const Certificate *subject, + AuthorityKeyIdentifier *ai) +{ + const Extension *e; + size_t size; + size_t i = 0; + + memset(ai, 0, sizeof(*ai)); + + e = find_extension(subject, &asn1_oid_id_x509_ce_authorityKeyIdentifier, &i); + if (e == NULL) + return HX509_EXTENSION_NOT_FOUND; + + return decode_AuthorityKeyIdentifier(e->extnValue.data, + e->extnValue.length, + ai, &size); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_find_extension_subject_key_id(const Certificate *issuer, + SubjectKeyIdentifier *si) +{ + const Extension *e; + size_t size; + size_t i = 0; + + memset(si, 0, sizeof(*si)); + + e = find_extension(issuer, &asn1_oid_id_x509_ce_subjectKeyIdentifier, &i); + if (e == NULL) + return HX509_EXTENSION_NOT_FOUND; + + return decode_SubjectKeyIdentifier(e->extnValue.data, + e->extnValue.length, + si, &size); +} + +static int +find_extension_name_constraints(const Certificate *subject, + NameConstraints *nc) +{ + const Extension *e; + size_t size; + size_t i = 0; + + memset(nc, 0, sizeof(*nc)); + + e = find_extension(subject, &asn1_oid_id_x509_ce_nameConstraints, &i); + if (e == NULL) + return HX509_EXTENSION_NOT_FOUND; + + return decode_NameConstraints(e->extnValue.data, + e->extnValue.length, + nc, &size); +} + +static int +find_extension_subject_alt_name(const Certificate *cert, size_t *i, + GeneralNames *sa) +{ + const Extension *e; + size_t size; + + memset(sa, 0, sizeof(*sa)); + + e = find_extension(cert, &asn1_oid_id_x509_ce_subjectAltName, i); + if (e == NULL) + return HX509_EXTENSION_NOT_FOUND; + + return decode_GeneralNames(e->extnValue.data, + e->extnValue.length, + sa, &size); +} + +static int +find_extension_eku(const Certificate *cert, ExtKeyUsage *eku) +{ + const Extension *e; + size_t size; + size_t i = 0; + + memset(eku, 0, sizeof(*eku)); + + e = find_extension(cert, &asn1_oid_id_x509_ce_extKeyUsage, &i); + if (e == NULL) + return HX509_EXTENSION_NOT_FOUND; + + return decode_ExtKeyUsage(e->extnValue.data, + e->extnValue.length, + eku, &size); +} + +static int +add_to_list(hx509_octet_string_list *list, const heim_octet_string *entry) +{ + void *p; + int ret; + + p = realloc(list->val, (list->len + 1) * sizeof(list->val[0])); + if (p == NULL) + return ENOMEM; + list->val = p; + ret = der_copy_octet_string(entry, &list->val[list->len]); + if (ret) + return ret; + list->len++; + return 0; +} + +/** + * Free a list of octet strings returned by another hx509 library + * function. + * + * @param list list to be freed. + * + * @ingroup hx509_misc + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_free_octet_string_list(hx509_octet_string_list *list) +{ + size_t i; + + if (list->val) { + for (i = 0; i < list->len; i++) + der_free_octet_string(&list->val[i]); + free(list->val); + } + list->val = NULL; + list->len = 0; +} + +/** + * Return a list of subjectAltNames specified by oid in the + * certificate. On error the + * + * The returned list of octet string should be freed with + * hx509_free_octet_string_list(). + * + * @param context A hx509 context. + * @param cert a hx509 certificate object. + * @param oid an oid to for SubjectAltName. + * @param list list of matching SubjectAltName. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cert_find_subjectAltName_otherName(hx509_context context, + hx509_cert cert, + const heim_oid *oid, + hx509_octet_string_list *list) +{ + GeneralNames sa; + int ret; + size_t i, j; + + list->val = NULL; + list->len = 0; + + i = 0; + while (1) { + ret = find_extension_subject_alt_name(_hx509_get_cert(cert), &i, &sa); + i++; + if (ret == HX509_EXTENSION_NOT_FOUND) { + return 0; + } else if (ret != 0) { + hx509_set_error_string(context, 0, ret, "Error searching for SAN"); + hx509_free_octet_string_list(list); + return ret; + } + + for (j = 0; j < sa.len; j++) { + if (sa.val[j].element == choice_GeneralName_otherName && + der_heim_oid_cmp(&sa.val[j].u.otherName.type_id, oid) == 0) + { + ret = add_to_list(list, &sa.val[j].u.otherName.value); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Error adding an exra SAN to " + "return list"); + hx509_free_octet_string_list(list); + free_GeneralNames(&sa); + return ret; + } + } + } + free_GeneralNames(&sa); + } +} + + +static int +check_key_usage(hx509_context context, const Certificate *cert, + unsigned flags, int req_present) +{ + const Extension *e; + KeyUsage ku; + size_t size; + int ret; + size_t i = 0; + uint64_t ku_flags; + + if (_hx509_cert_get_version(cert) < 3) + return 0; + + e = find_extension(cert, &asn1_oid_id_x509_ce_keyUsage, &i); + if (e == NULL) { + if (req_present) { + hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING, + "Required extension key " + "usage missing from certificate"); + return HX509_KU_CERT_MISSING; + } + return 0; + } + + ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, &ku, &size); + if (ret) + return ret; + ku_flags = KeyUsage2int(ku); + if ((ku_flags & flags) != flags) { + uint64_t missing = (~ku_flags) & flags; + char buf[256], *name; + + int result = unparse_flags(missing, asn1_KeyUsage_units(), + buf, sizeof(buf)); + _hx509_unparse_Name(&cert->tbsCertificate.subject, &name); + hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING, + "Key usage %s required but missing " + "from certificate %s", + (result > 0) ? buf : "<unknown>", + name ? name : "<unknown>"); + free(name); + return HX509_KU_CERT_MISSING; + } + return 0; +} + +/* + * Return 0 on matching key usage 'flags' for 'cert', otherwise return + * an error code. If 'req_present' the existence is required of the + * KeyUsage extension. + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_check_key_usage(hx509_context context, hx509_cert cert, + unsigned flags, int req_present) +{ + return check_key_usage(context, _hx509_get_cert(cert), flags, req_present); +} + +enum certtype { PROXY_CERT, EE_CERT, CA_CERT }; + +static int +check_basic_constraints(hx509_context context, const Certificate *cert, + enum certtype type, size_t depth) +{ + BasicConstraints bc; + const Extension *e; + size_t size; + int ret; + size_t i = 0; + + if (_hx509_cert_get_version(cert) < 3) + return 0; + + e = find_extension(cert, &asn1_oid_id_x509_ce_basicConstraints, &i); + if (e == NULL) { + switch(type) { + case PROXY_CERT: + case EE_CERT: + return 0; + case CA_CERT: { + char *name; + ret = _hx509_unparse_Name(&cert->tbsCertificate.subject, &name); + assert(ret == 0); + hx509_set_error_string(context, 0, HX509_EXTENSION_NOT_FOUND, + "basicConstraints missing from " + "CA certifiacte %s", name); + free(name); + return HX509_EXTENSION_NOT_FOUND; + } + } + } + + ret = decode_BasicConstraints(e->extnValue.data, + e->extnValue.length, &bc, + &size); + if (ret) + return ret; + switch(type) { + case PROXY_CERT: + if (bc.cA) + ret = HX509_PARENT_IS_CA; + break; + case EE_CERT: + ret = 0; + break; + case CA_CERT: + if (!bc.cA) + ret = HX509_PARENT_NOT_CA; + else if (bc.pathLenConstraint) + if (depth - 1 > *bc.pathLenConstraint) + ret = HX509_CA_PATH_TOO_DEEP; + break; + } + free_BasicConstraints(&bc); + return ret; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_cert_is_parent_cmp(const Certificate *subject, + const Certificate *issuer, + int allow_self_signed) +{ + int diff; + AuthorityKeyIdentifier ai; + SubjectKeyIdentifier si; + int ret_ai, ret_si, ret; + + ret = _hx509_name_cmp(&issuer->tbsCertificate.subject, + &subject->tbsCertificate.issuer, + &diff); + if (ret) + return ret; + if (diff) + return diff; + + memset(&ai, 0, sizeof(ai)); + memset(&si, 0, sizeof(si)); + + /* + * Try to find AuthorityKeyIdentifier, if it's not present in the + * subject certificate nor the parent. + */ + + ret_ai = find_extension_auth_key_id(subject, &ai); + if (ret_ai && ret_ai != HX509_EXTENSION_NOT_FOUND) + return 1; + ret_si = _hx509_find_extension_subject_key_id(issuer, &si); + if (ret_si && ret_si != HX509_EXTENSION_NOT_FOUND) + return -1; + + if (ret_si && ret_ai) + goto out; + if (ret_ai) + goto out; + if (ret_si) { + if (allow_self_signed) { + diff = 0; + goto out; + } else if (ai.keyIdentifier) { + diff = -1; + goto out; + } + } + + if (ai.keyIdentifier == NULL) { + Name name; + + if (ai.authorityCertIssuer == NULL) + return -1; + if (ai.authorityCertSerialNumber == NULL) + return -1; + + diff = der_heim_integer_cmp(ai.authorityCertSerialNumber, + &issuer->tbsCertificate.serialNumber); + if (diff) + return diff; + if (ai.authorityCertIssuer->len != 1) + return -1; + if (ai.authorityCertIssuer->val[0].element != choice_GeneralName_directoryName) + return -1; + + name.element = (enum Name_enum) + ai.authorityCertIssuer->val[0].u.directoryName.element; + name.u.rdnSequence = + ai.authorityCertIssuer->val[0].u.directoryName.u.rdnSequence; + + ret = _hx509_name_cmp(&issuer->tbsCertificate.subject, + &name, + &diff); + if (ret) + return ret; + if (diff) + return diff; + diff = 0; + } else + diff = der_heim_octet_string_cmp(ai.keyIdentifier, &si); + if (diff) + goto out; + + out: + free_AuthorityKeyIdentifier(&ai); + free_SubjectKeyIdentifier(&si); + return diff; +} + +static int +certificate_is_anchor(hx509_context context, + hx509_certs trust_anchors, + const hx509_cert cert) +{ + hx509_query q; + hx509_cert c; + int ret; + + if (trust_anchors == NULL) + return 0; + + _hx509_query_clear(&q); + + q.match = HX509_QUERY_MATCH_CERTIFICATE; + q.certificate = _hx509_get_cert(cert); + + ret = hx509_certs_find(context, trust_anchors, &q, &c); + if (ret == 0) + hx509_cert_free(c); + return ret == 0; +} + +static int +certificate_is_self_signed(hx509_context context, + const Certificate *cert, + int *self_signed) +{ + int ret, diff; + ret = _hx509_name_cmp(&cert->tbsCertificate.subject, + &cert->tbsCertificate.issuer, &diff); + *self_signed = (diff == 0); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to check if self signed"); + } else + ret = _hx509_self_signed_valid(context, &cert->signatureAlgorithm); + + return ret; +} + +/* + * The subjectName is "null" when it's empty set of relative DBs. + */ + +static int +subject_null_p(const Certificate *c) +{ + return c->tbsCertificate.subject.u.rdnSequence.len == 0; +} + + +static int +find_parent(hx509_context context, + time_t time_now, + hx509_certs trust_anchors, + hx509_path *path, + hx509_certs pool, + hx509_cert current, + hx509_cert *parent) +{ + AuthorityKeyIdentifier ai; + hx509_query q; + int ret; + + *parent = NULL; + memset(&ai, 0, sizeof(ai)); + + _hx509_query_clear(&q); + + if (!subject_null_p(current->data)) { + q.match |= HX509_QUERY_FIND_ISSUER_CERT; + q.subject = _hx509_get_cert(current); + } else { + ret = find_extension_auth_key_id(current->data, &ai); + if (ret) { + hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED, + "Subjectless certificate missing AuthKeyID"); + return HX509_CERTIFICATE_MALFORMED; + } + + if (ai.keyIdentifier == NULL) { + free_AuthorityKeyIdentifier(&ai); + hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED, + "Subjectless certificate missing keyIdentifier " + "inside AuthKeyID"); + return HX509_CERTIFICATE_MALFORMED; + } + + q.subject_id = ai.keyIdentifier; + q.match = HX509_QUERY_MATCH_SUBJECT_KEY_ID; + } + + q.path = path; + q.match |= HX509_QUERY_NO_MATCH_PATH; + + if (pool) { + q.timenow = time_now; + q.match |= HX509_QUERY_MATCH_TIME; + + ret = hx509_certs_find(context, pool, &q, parent); + if (ret == 0) { + free_AuthorityKeyIdentifier(&ai); + return 0; + } + q.match &= ~HX509_QUERY_MATCH_TIME; + } + + if (trust_anchors) { + ret = hx509_certs_find(context, trust_anchors, &q, parent); + if (ret == 0) { + free_AuthorityKeyIdentifier(&ai); + return ret; + } + } + free_AuthorityKeyIdentifier(&ai); + + { + hx509_name name; + char *str; + + ret = hx509_cert_get_subject(current, &name); + if (ret) { + hx509_clear_error_string(context); + return HX509_ISSUER_NOT_FOUND; + } + ret = hx509_name_to_string(name, &str); + hx509_name_free(&name); + if (ret) { + hx509_clear_error_string(context); + return HX509_ISSUER_NOT_FOUND; + } + + hx509_set_error_string(context, 0, HX509_ISSUER_NOT_FOUND, + "Failed to find issuer for " + "certificate with subject: '%s'", str); + free(str); + } + return HX509_ISSUER_NOT_FOUND; +} + +/* + * + */ + +static int +is_proxy_cert(hx509_context context, + const Certificate *cert, + ProxyCertInfo *rinfo) +{ + ProxyCertInfo info; + const Extension *e; + size_t size; + int ret; + size_t i = 0; + + if (rinfo) + memset(rinfo, 0, sizeof(*rinfo)); + + e = find_extension(cert, &asn1_oid_id_pkix_pe_proxyCertInfo, &i); + if (e == NULL) { + hx509_clear_error_string(context); + return HX509_EXTENSION_NOT_FOUND; + } + + ret = decode_ProxyCertInfo(e->extnValue.data, + e->extnValue.length, + &info, + &size); + if (ret) { + hx509_clear_error_string(context); + return ret; + } + if (size != e->extnValue.length) { + free_ProxyCertInfo(&info); + hx509_clear_error_string(context); + return HX509_EXTRA_DATA_AFTER_STRUCTURE; + } + if (rinfo == NULL) + free_ProxyCertInfo(&info); + else + *rinfo = info; + + return 0; +} + +/* + * Path operations are like MEMORY based keyset, but with exposed + * internal so we can do easy searches. + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_path_append(hx509_context context, hx509_path *path, hx509_cert cert) +{ + hx509_cert *val; + val = realloc(path->val, (path->len + 1) * sizeof(path->val[0])); + if (val == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + + path->val = val; + path->val[path->len] = hx509_cert_ref(cert); + path->len++; + + return 0; +} + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_path_free(hx509_path *path) +{ + unsigned i; + + for (i = 0; i < path->len; i++) + hx509_cert_free(path->val[i]); + free(path->val); + path->val = NULL; + path->len = 0; +} + +/* + * Find path by looking up issuer for the top certificate and continue + * until an anchor certificate is found or max limit is found. A + * certificate never included twice in the path. + * + * If the trust anchors are not given, calculate optimistic path, just + * follow the chain upward until we no longer find a parent or we hit + * the max path limit. In this case, a failure will always be returned + * depending on what error condition is hit first. + * + * The path includes a path from the top certificate to the anchor + * certificate. + * + * The caller needs to free `path´ both on successful built path and + * failure. + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_calculate_path(hx509_context context, + int flags, + time_t time_now, + hx509_certs anchors, + unsigned int max_depth, + hx509_cert cert, + hx509_certs pool, + hx509_path *path) +{ + hx509_cert parent, current; + int ret; + + if (max_depth == 0) + max_depth = HX509_VERIFY_MAX_DEPTH; + + ret = _hx509_path_append(context, path, cert); + if (ret) + return ret; + + current = hx509_cert_ref(cert); + + while (!certificate_is_anchor(context, anchors, current)) { + + ret = find_parent(context, time_now, anchors, path, + pool, current, &parent); + hx509_cert_free(current); + if (ret) + return ret; + + ret = _hx509_path_append(context, path, parent); + if (ret) + return ret; + current = parent; + + if (path->len > max_depth) { + hx509_cert_free(current); + hx509_set_error_string(context, 0, HX509_PATH_TOO_LONG, + "Path too long while bulding " + "certificate chain"); + return HX509_PATH_TOO_LONG; + } + } + + if ((flags & HX509_CALCULATE_PATH_NO_ANCHOR) && + path->len > 0 && + certificate_is_anchor(context, anchors, path->val[path->len - 1])) + { + hx509_cert_free(path->val[path->len - 1]); + path->len--; + } + + hx509_cert_free(current); + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_AlgorithmIdentifier_cmp(const AlgorithmIdentifier *p, + const AlgorithmIdentifier *q) +{ + int diff; + diff = der_heim_oid_cmp(&p->algorithm, &q->algorithm); + if (diff) + return diff; + if (p->parameters) { + if (q->parameters) + return heim_any_cmp(p->parameters, + q->parameters); + else + return 1; + } else { + if (q->parameters) + return -1; + else + return 0; + } +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_Certificate_cmp(const Certificate *p, const Certificate *q) +{ + int diff; + diff = der_heim_bit_string_cmp(&p->signatureValue, &q->signatureValue); + if (diff) + return diff; + diff = _hx509_AlgorithmIdentifier_cmp(&p->signatureAlgorithm, + &q->signatureAlgorithm); + if (diff) + return diff; + diff = der_heim_octet_string_cmp(&p->tbsCertificate._save, + &q->tbsCertificate._save); + return diff; +} + +/** + * Compare to hx509 certificate object, useful for sorting. + * + * @param p a hx509 certificate object. + * @param q a hx509 certificate object. + * + * @return 0 the objects are the same, returns > 0 is p is "larger" + * then q, < 0 if p is "smaller" then q. + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cert_cmp(hx509_cert p, hx509_cert q) +{ + return _hx509_Certificate_cmp(p->data, q->data); +} + +/** + * Return the name of the issuer of the hx509 certificate. + * + * @param p a hx509 certificate object. + * @param name a pointer to a hx509 name, should be freed by + * hx509_name_free(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cert_get_issuer(hx509_cert p, hx509_name *name) +{ + return _hx509_name_from_Name(&p->data->tbsCertificate.issuer, name); +} + +/** + * Return the name of the subject of the hx509 certificate. + * + * @param p a hx509 certificate object. + * @param name a pointer to a hx509 name, should be freed by + * hx509_name_free(). See also hx509_cert_get_base_subject(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cert_get_subject(hx509_cert p, hx509_name *name) +{ + return _hx509_name_from_Name(&p->data->tbsCertificate.subject, name); +} + +/** + * Return the name of the base subject of the hx509 certificate. If + * the certiicate is a verified proxy certificate, the this function + * return the base certificate (root of the proxy chain). If the proxy + * certificate is not verified with the base certificate + * HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED is returned. + * + * @param context a hx509 context. + * @param c a hx509 certificate object. + * @param name a pointer to a hx509 name, should be freed by + * hx509_name_free(). See also hx509_cert_get_subject(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cert_get_base_subject(hx509_context context, hx509_cert c, + hx509_name *name) +{ + if (c->basename) + return hx509_name_copy(context, c->basename, name); + if (is_proxy_cert(context, c->data, NULL) == 0) { + int ret = HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED; + hx509_set_error_string(context, 0, ret, + "Proxy certificate has not been " + "canonicalized yet: no base name"); + return ret; + } + return _hx509_name_from_Name(&c->data->tbsCertificate.subject, name); +} + +/** + * Get serial number of the certificate. + * + * @param p a hx509 certificate object. + * @param i serial number, should be freed ith der_free_heim_integer(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cert_get_serialnumber(hx509_cert p, heim_integer *i) +{ + return der_copy_heim_integer(&p->data->tbsCertificate.serialNumber, i); +} + +/** + * Get notBefore time of the certificate. + * + * @param p a hx509 certificate object. + * + * @return return not before time + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION time_t HX509_LIB_CALL +hx509_cert_get_notBefore(hx509_cert p) +{ + return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notBefore); +} + +/** + * Get notAfter time of the certificate. + * + * @param p a hx509 certificate object. + * + * @return return not after time. + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION time_t HX509_LIB_CALL +hx509_cert_get_notAfter(hx509_cert p) +{ + return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notAfter); +} + +/** + * Get a maximum Kerberos credential lifetime from a Heimdal certificate + * extension. + * + * @param context hx509 context. + * @param cert Certificate. + * @param bound If larger than zero, return no more than this. + * + * @return maximum ticket lifetime. + */ +HX509_LIB_FUNCTION time_t HX509_LIB_CALL +hx509_cert_get_pkinit_max_life(hx509_context context, + hx509_cert cert, + time_t bound) +{ + HeimPkinitPrincMaxLifeSecs r = 0; + size_t sz, i; + time_t b, e; + int ret; + + for (i = 0; i < cert->data->tbsCertificate.extensions->len; i++) { + Extension *ext = &cert->data->tbsCertificate.extensions->val[i]; + + if (ext->_ioschoice_extnValue.element != + choice_Extension_iosnumunknown && + ext->_ioschoice_extnValue.element != + choice_Extension_iosnum_id_heim_ce_pkinit_princ_max_life) + continue; + if (ext->_ioschoice_extnValue.element == choice_Extension_iosnumunknown && + der_heim_oid_cmp(&asn1_oid_id_heim_ce_pkinit_princ_max_life, &ext->extnID)) + continue; + if (ext->_ioschoice_extnValue.u.ext_HeimPkinitPrincMaxLife) { + r = *ext->_ioschoice_extnValue.u.ext_HeimPkinitPrincMaxLife; + } else { + ret = decode_HeimPkinitPrincMaxLifeSecs(ext->extnValue.data, + ext->extnValue.length, + &r, &sz); + /* No need to free_HeimPkinitPrincMaxLifeSecs(); it's an int */ + if (ret || r < 1) + return 0; + } + if (bound > 0 && r > bound) + return bound; + return r; + } + if (hx509_cert_check_eku(context, cert, + &asn1_oid_id_heim_eku_pkinit_certlife_is_max_life, 0)) + return 0; + b = hx509_cert_get_notBefore(cert); + e = hx509_cert_get_notAfter(cert); + if (e > b) + r = e - b; + if (bound > 0 && r > bound) + return bound; + return r; +} + +/** + * Get the SubjectPublicKeyInfo structure from the hx509 certificate. + * + * @param context a hx509 context. + * @param p a hx509 certificate object. + * @param spki SubjectPublicKeyInfo, should be freed with + * free_SubjectPublicKeyInfo(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cert_get_SPKI(hx509_context context, hx509_cert p, SubjectPublicKeyInfo *spki) +{ + int ret; + + ret = copy_SubjectPublicKeyInfo(&p->data->tbsCertificate.subjectPublicKeyInfo, spki); + if (ret) + hx509_set_error_string(context, 0, ret, "Failed to copy SPKI"); + return ret; +} + +/** + * Get the AlgorithmIdentifier from the hx509 certificate. + * + * @param context a hx509 context. + * @param p a hx509 certificate object. + * @param alg AlgorithmIdentifier, should be freed with + * free_AlgorithmIdentifier(). The algorithmidentifier is + * typicly rsaEncryption, or id-ecPublicKey, or some other + * public key mechanism. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cert_get_SPKI_AlgorithmIdentifier(hx509_context context, + hx509_cert p, + AlgorithmIdentifier *alg) +{ + int ret; + + ret = copy_AlgorithmIdentifier(&p->data->tbsCertificate.subjectPublicKeyInfo.algorithm, alg); + if (ret) + hx509_set_error_string(context, 0, ret, + "Failed to copy SPKI AlgorithmIdentifier"); + return ret; +} + +static int +get_x_unique_id(hx509_context context, const char *name, + const heim_bit_string *cert, heim_bit_string *subject) +{ + int ret; + + if (cert == NULL) { + ret = HX509_EXTENSION_NOT_FOUND; + hx509_set_error_string(context, 0, ret, "%s unique id doesn't exist", name); + return ret; + } + ret = der_copy_bit_string(cert, subject); + if (ret) { + hx509_set_error_string(context, 0, ret, "malloc out of memory", name); + return ret; + } + return 0; +} + +/** + * Get a copy of the Issuer Unique ID + * + * @param context a hx509_context + * @param p a hx509 certificate + * @param issuer the issuer id returned, free with der_free_bit_string() + * + * @return An hx509 error code, see hx509_get_error_string(). The + * error code HX509_EXTENSION_NOT_FOUND is returned if the certificate + * doesn't have a issuerUniqueID + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cert_get_issuer_unique_id(hx509_context context, hx509_cert p, heim_bit_string *issuer) +{ + return get_x_unique_id(context, "issuer", p->data->tbsCertificate.issuerUniqueID, issuer); +} + +/** + * Get a copy of the Subect Unique ID + * + * @param context a hx509_context + * @param p a hx509 certificate + * @param subject the subject id returned, free with der_free_bit_string() + * + * @return An hx509 error code, see hx509_get_error_string(). The + * error code HX509_EXTENSION_NOT_FOUND is returned if the certificate + * doesn't have a subjectUniqueID + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cert_get_subject_unique_id(hx509_context context, hx509_cert p, heim_bit_string *subject) +{ + return get_x_unique_id(context, "subject", p->data->tbsCertificate.subjectUniqueID, subject); +} + + +HX509_LIB_FUNCTION hx509_private_key HX509_LIB_CALL +_hx509_cert_private_key(hx509_cert p) +{ + return p->private_key; +} + +/** + * Indicate whether a hx509_cert has a private key. + * + * @param p a hx509 certificate + * + * @return 1 if p has a private key, 0 otherwise. + * + * @ingroup hx509_cert + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cert_have_private_key(hx509_cert p) +{ + return p->private_key ? 1 : 0; +} + +/** + * Indicate whether a hx509_cert has a private key only (no certificate). + * + * @param p a hx509 certificate + * + * @return 1 if p has a private key only (no certificate), 0 otherwise. + * + * @ingroup hx509_cert + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cert_have_private_key_only(hx509_cert p) +{ + return p->private_key && !p->data ? 1 : 0; +} + + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_cert_private_key_exportable(hx509_cert p) +{ + if (p->private_key == NULL) + return 0; + return _hx509_private_key_exportable(p->private_key); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_cert_private_decrypt(hx509_context context, + const heim_octet_string *ciphertext, + const heim_oid *encryption_oid, + hx509_cert p, + heim_octet_string *cleartext) +{ + cleartext->data = NULL; + cleartext->length = 0; + + if (p->private_key == NULL) { + hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING, + "Private key missing"); + return HX509_PRIVATE_KEY_MISSING; + } + + return hx509_private_key_private_decrypt(context, + ciphertext, + encryption_oid, + p->private_key, + cleartext); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cert_public_encrypt(hx509_context context, + const heim_octet_string *cleartext, + const hx509_cert p, + heim_oid *encryption_oid, + heim_octet_string *ciphertext) +{ + return _hx509_public_encrypt(context, + cleartext, p->data, + encryption_oid, ciphertext); +} + +/* + * + */ + +HX509_LIB_FUNCTION time_t HX509_LIB_CALL +_hx509_Time2time_t(const Time *t) +{ + switch(t->element) { + case choice_Time_utcTime: + return t->u.utcTime; + case choice_Time_generalTime: + return t->u.generalTime; + } + return 0; +} + +/* + * + */ + +static int +init_name_constraints(hx509_name_constraints *nc) +{ + memset(nc, 0, sizeof(*nc)); + return 0; +} + +static int +add_name_constraints(hx509_context context, const Certificate *c, int not_ca, + hx509_name_constraints *nc) +{ + NameConstraints tnc; + int ret; + + ret = find_extension_name_constraints(c, &tnc); + if (ret == HX509_EXTENSION_NOT_FOUND) + return 0; + else if (ret) { + hx509_set_error_string(context, 0, ret, "Failed getting NameConstraints"); + return ret; + } else if (not_ca) { + ret = HX509_VERIFY_CONSTRAINTS; + hx509_set_error_string(context, 0, ret, "Not a CA and " + "have NameConstraints"); + } else { + NameConstraints *val; + val = realloc(nc->val, sizeof(nc->val[0]) * (nc->len + 1)); + if (val == NULL) { + hx509_clear_error_string(context); + ret = ENOMEM; + goto out; + } + nc->val = val; + ret = copy_NameConstraints(&tnc, &nc->val[nc->len]); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + nc->len += 1; + } +out: + free_NameConstraints(&tnc); + return ret; +} + +static int +match_RDN(const RelativeDistinguishedName *c, + const RelativeDistinguishedName *n) +{ + size_t i; + + if (c->len != n->len) + return HX509_NAME_CONSTRAINT_ERROR; + + for (i = 0; i < n->len; i++) { + int diff, ret; + + if (der_heim_oid_cmp(&c->val[i].type, &n->val[i].type) != 0) + return HX509_NAME_CONSTRAINT_ERROR; + ret = _hx509_name_ds_cmp(&c->val[i].value, &n->val[i].value, &diff); + if (ret) + return ret; + if (diff != 0) + return HX509_NAME_CONSTRAINT_ERROR; + } + return 0; +} + +static int +match_X501Name(const Name *c, const Name *n) +{ + size_t i; + int ret; + + if (c->element != choice_Name_rdnSequence + || n->element != choice_Name_rdnSequence) + return 0; + if (c->u.rdnSequence.len > n->u.rdnSequence.len) + return HX509_NAME_CONSTRAINT_ERROR; + for (i = 0; i < c->u.rdnSequence.len; i++) { + ret = match_RDN(&c->u.rdnSequence.val[i], &n->u.rdnSequence.val[i]); + if (ret) + return ret; + } + return 0; +} + + +static int +match_general_name(const GeneralName *c, const GeneralName *n, int *match) +{ + /* + * Name constraints only apply to the same name type, see RFC3280, + * 4.2.1.11. + */ + assert(c->element == n->element); + + switch(c->element) { + case choice_GeneralName_otherName: + if (der_heim_oid_cmp(&c->u.otherName.type_id, + &n->u.otherName.type_id) != 0) + return HX509_NAME_CONSTRAINT_ERROR; + if (heim_any_cmp(&c->u.otherName.value, + &n->u.otherName.value) != 0) + return HX509_NAME_CONSTRAINT_ERROR; + *match = 1; + return 0; + case choice_GeneralName_rfc822Name: { + const char *s; + size_t len1, len2; + s = memchr(c->u.rfc822Name.data, '@', c->u.rfc822Name.length); + if (s) { + if (der_printable_string_cmp(&c->u.rfc822Name, &n->u.rfc822Name) != 0) + return HX509_NAME_CONSTRAINT_ERROR; + } else { + s = memchr(n->u.rfc822Name.data, '@', n->u.rfc822Name.length); + if (s == NULL) + return HX509_NAME_CONSTRAINT_ERROR; + len1 = c->u.rfc822Name.length; + len2 = n->u.rfc822Name.length - + (s - ((char *)n->u.rfc822Name.data)); + if (len1 > len2) + return HX509_NAME_CONSTRAINT_ERROR; + if (memcmp(s + 1 + len2 - len1, c->u.rfc822Name.data, len1) != 0) + return HX509_NAME_CONSTRAINT_ERROR; + if (len1 < len2 && s[len2 - len1 + 1] != '.') + return HX509_NAME_CONSTRAINT_ERROR; + } + *match = 1; + return 0; + } + case choice_GeneralName_dNSName: { + size_t lenc, lenn; + char *ptr; + + lenc = c->u.dNSName.length; + lenn = n->u.dNSName.length; + if (lenc > lenn) + return HX509_NAME_CONSTRAINT_ERROR; + ptr = n->u.dNSName.data; + if (memcmp(&ptr[lenn - lenc], c->u.dNSName.data, lenc) != 0) + return HX509_NAME_CONSTRAINT_ERROR; + if (lenn != lenc && ptr[lenn - lenc - 1] != '.') + return HX509_NAME_CONSTRAINT_ERROR; + *match = 1; + return 0; + } + case choice_GeneralName_directoryName: { + Name c_name, n_name; + int ret; + + c_name._save.data = NULL; + c_name._save.length = 0; + c_name.element = (enum Name_enum)c->u.directoryName.element; + c_name.u.rdnSequence = c->u.directoryName.u.rdnSequence; + + n_name._save.data = NULL; + n_name._save.length = 0; + n_name.element = (enum Name_enum)n->u.directoryName.element; + n_name.u.rdnSequence = n->u.directoryName.u.rdnSequence; + + ret = match_X501Name(&c_name, &n_name); + if (ret == 0) + *match = 1; + return ret; + } + case choice_GeneralName_uniformResourceIdentifier: + case choice_GeneralName_iPAddress: + case choice_GeneralName_registeredID: + default: + return HX509_NAME_CONSTRAINT_ERROR; + } +} + +static int +match_alt_name(const GeneralName *n, const Certificate *c, + int *same, int *match) +{ + GeneralNames sa; + int ret = 0; + size_t i, j; + + i = 0; + do { + ret = find_extension_subject_alt_name(c, &i, &sa); + if (ret == HX509_EXTENSION_NOT_FOUND) { + ret = 0; + break; + } else if (ret != 0) + break; + + for (j = 0; j < sa.len; j++) { + if (n->element == sa.val[j].element) { + *same = 1; + match_general_name(n, &sa.val[j], match); + } + } + free_GeneralNames(&sa); + } while (1); + return ret; +} + + +static int +match_tree(const GeneralSubtrees *t, const Certificate *c, int *match) +{ + int name, alt_name, same; + unsigned int i; + int ret = 0; + + name = alt_name = same = *match = 0; + for (i = 0; i < t->len; i++) { + if (t->val[i].minimum && t->val[i].maximum) + return HX509_RANGE; + + /* + * If the constraint apply to directoryNames, test is with + * subjectName of the certificate if the certificate have a + * non-null (empty) subjectName. + */ + + if (t->val[i].base.element == choice_GeneralName_directoryName + && !subject_null_p(c)) + { + GeneralName certname; + + memset(&certname, 0, sizeof(certname)); + certname.element = choice_GeneralName_directoryName; + certname.u.directoryName.element = (enum Name_enum) + c->tbsCertificate.subject.element; + certname.u.directoryName.u.rdnSequence = + c->tbsCertificate.subject.u.rdnSequence; + + match_general_name(&t->val[i].base, &certname, &name); + } + + /* Handle subjectAltNames, this is icky since they + * restrictions only apply if the subjectAltName is of the + * same type. So if there have been a match of type, require + * altname to be set. + */ + match_alt_name(&t->val[i].base, c, &same, &alt_name); + } + if (name && (!same || alt_name)) + *match = 1; + return ret; +} + +static int +check_name_constraints(hx509_context context, + const hx509_name_constraints *nc, + const Certificate *c) +{ + int match, ret; + size_t i; + + for (i = 0 ; i < nc->len; i++) { + GeneralSubtrees gs; + + if (nc->val[i].permittedSubtrees) { + GeneralSubtrees_SET(&gs, nc->val[i].permittedSubtrees); + ret = match_tree(&gs, c, &match); + if (ret) { + hx509_clear_error_string(context); + return ret; + } + /* allow null subjectNames, they wont matches anything */ + if (match == 0 && !subject_null_p(c)) { + hx509_set_error_string(context, 0, HX509_VERIFY_CONSTRAINTS, + "Error verifying constraints: " + "certificate didn't match any " + "permitted subtree"); + return HX509_VERIFY_CONSTRAINTS; + } + } + if (nc->val[i].excludedSubtrees) { + GeneralSubtrees_SET(&gs, nc->val[i].excludedSubtrees); + ret = match_tree(&gs, c, &match); + if (ret) { + hx509_clear_error_string(context); + return ret; + } + if (match) { + hx509_set_error_string(context, 0, HX509_VERIFY_CONSTRAINTS, + "Error verifying constraints: " + "certificate included in excluded " + "subtree"); + return HX509_VERIFY_CONSTRAINTS; + } + } + } + return 0; +} + +static void +free_name_constraints(hx509_name_constraints *nc) +{ + size_t i; + + for (i = 0 ; i < nc->len; i++) + free_NameConstraints(&nc->val[i]); + free(nc->val); +} + +/** + * Build and verify the path for the certificate to the trust anchor + * specified in the verify context. The path is constructed from the + * certificate, the pool and the trust anchors. + * + * @param context A hx509 context. + * @param ctx A hx509 verification context. + * @param cert the certificate to build the path from. + * @param pool A keyset of certificates to build the chain from. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_verify + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_verify_path(hx509_context context, + hx509_verify_ctx ctx, + hx509_cert cert, + hx509_certs pool) +{ + hx509_name_constraints nc; + hx509_path path; + int ret, proxy_cert_depth, selfsigned_depth, diff; + size_t i, k; + enum certtype type; + Name proxy_issuer; + hx509_certs anchors = NULL; + + memset(&proxy_issuer, 0, sizeof(proxy_issuer)); + + if ((ctx->flags & HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE) == 0 && + is_proxy_cert(context, cert->data, NULL) == 0) + { + ret = HX509_PROXY_CERT_INVALID; + hx509_set_error_string(context, 0, ret, + "Proxy certificate is not allowed as an EE " + "certificate if proxy certificate is disabled"); + return ret; + } + + ret = init_name_constraints(&nc); + if (ret) + return ret; + + path.val = NULL; + path.len = 0; + + if ((ctx->flags & HX509_VERIFY_CTX_F_TIME_SET) == 0) + ctx->time_now = time(NULL); + + /* + * + */ + if (ctx->trust_anchors) + anchors = hx509_certs_ref(ctx->trust_anchors); + else if (context->default_trust_anchors && ALLOW_DEF_TA(ctx)) + anchors = hx509_certs_ref(context->default_trust_anchors); + else { + ret = hx509_certs_init(context, "MEMORY:no-TA", 0, NULL, &anchors); + if (ret) + goto out; + } + + /* + * Calculate the path from the certificate user presented to the + * to an anchor. + */ + ret = _hx509_calculate_path(context, 0, ctx->time_now, + anchors, ctx->max_depth, + cert, pool, &path); + if (ret) + goto out; + + /* + * Check CA and proxy certificate chain from the top of the + * certificate chain. Also check certificate is valid with respect + * to the current time. + * + */ + + proxy_cert_depth = 0; + selfsigned_depth = 0; + + if (ctx->flags & HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE) + type = PROXY_CERT; + else + type = EE_CERT; + + for (i = 0; i < path.len; i++) { + Certificate *c; + time_t t; + + c = _hx509_get_cert(path.val[i]); + + /* + * Lets do some basic check on issuer like + * keyUsage.keyCertSign and basicConstraints.cA bit depending + * on what type of certificate this is. + */ + + switch (type) { + case CA_CERT: + + /* XXX make constants for keyusage */ + ret = check_key_usage(context, c, 1 << 5, + REQUIRE_RFC3280(ctx) ? TRUE : FALSE); + if (ret) { + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + "Key usage missing from CA certificate"); + goto out; + } + + /* self signed cert doesn't add to path length */ + if (i + 1 != path.len) { + int selfsigned; + + ret = certificate_is_self_signed(context, c, &selfsigned); + if (ret) + goto out; + if (selfsigned) + selfsigned_depth++; + } + + break; + case PROXY_CERT: { + ProxyCertInfo info; + + if (is_proxy_cert(context, c, &info) == 0) { + size_t j; + + if (info.pCPathLenConstraint != NULL && + *info.pCPathLenConstraint < i) + { + free_ProxyCertInfo(&info); + ret = HX509_PATH_TOO_LONG; + hx509_set_error_string(context, 0, ret, + "Proxy certificate chain " + "longer than allowed"); + goto out; + } + /* XXX MUST check info.proxyPolicy */ + free_ProxyCertInfo(&info); + + j = 0; + if (find_extension(c, &asn1_oid_id_x509_ce_subjectAltName, &j)) { + ret = HX509_PROXY_CERT_INVALID; + hx509_set_error_string(context, 0, ret, + "Proxy certificate has explicitly " + "forbidden subjectAltName"); + goto out; + } + + j = 0; + if (find_extension(c, &asn1_oid_id_x509_ce_issuerAltName, &j)) { + ret = HX509_PROXY_CERT_INVALID; + hx509_set_error_string(context, 0, ret, + "Proxy certificate has explicitly " + "forbidden issuerAltName"); + goto out; + } + + /* + * The subject name of the proxy certificate should be + * CN=XXX,<proxy issuer>, prune of CN and check if its + * the same over the whole chain of proxy certs and + * then check with the EE cert when we get to it. + */ + + if (proxy_cert_depth) { + ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.subject, &diff); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + if (diff) { + ret = HX509_PROXY_CERT_NAME_WRONG; + hx509_set_error_string(context, 0, ret, + "Base proxy name not right"); + goto out; + } + } + + free_Name(&proxy_issuer); + + ret = copy_Name(&c->tbsCertificate.subject, &proxy_issuer); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + + j = proxy_issuer.u.rdnSequence.len; + if (proxy_issuer.u.rdnSequence.len < 2 + || proxy_issuer.u.rdnSequence.val[j - 1].len > 1 + || der_heim_oid_cmp(&proxy_issuer.u.rdnSequence.val[j - 1].val[0].type, + &asn1_oid_id_at_commonName)) + { + ret = HX509_PROXY_CERT_NAME_WRONG; + hx509_set_error_string(context, 0, ret, + "Proxy name too short or " + "does not have Common name " + "at the top"); + goto out; + } + + free_RelativeDistinguishedName(&proxy_issuer.u.rdnSequence.val[j - 1]); + proxy_issuer.u.rdnSequence.len -= 1; + + ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.issuer, &diff); + if (ret) { + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + if (diff != 0) { + ret = HX509_PROXY_CERT_NAME_WRONG; + hx509_set_error_string(context, 0, ret, + "Proxy issuer name not as expected"); + goto out; + } + + break; + } else { + /* + * Now we are done with the proxy certificates, this + * cert was an EE cert and we we will fall though to + * EE checking below. + */ + type = EE_CERT; + } + } + fallthrough; + case EE_CERT: + /* + * If there where any proxy certificates in the chain + * (proxy_cert_depth > 0), check that the proxy issuer + * matched proxy certificates "base" subject. + */ + if (proxy_cert_depth) { + + ret = _hx509_name_cmp(&proxy_issuer, + &c->tbsCertificate.subject, &diff); + if (ret) { + hx509_set_error_string(context, 0, ret, "out of memory"); + goto out; + } + if (diff) { + ret = HX509_PROXY_CERT_NAME_WRONG; + hx509_clear_error_string(context); + goto out; + } + if (cert->basename) + hx509_name_free(&cert->basename); + + ret = _hx509_name_from_Name(&proxy_issuer, &cert->basename); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + } + + break; + } + + ret = check_basic_constraints(context, c, type, + i - proxy_cert_depth - selfsigned_depth); + if (ret) + goto out; + + /* + * Don't check the trust anchors expiration time since they + * are transported out of band, from RFC3820. + */ + if (i + 1 != path.len || CHECK_TA(ctx)) { + + t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore); + if (t > ctx->time_now) { + ret = HX509_CERT_USED_BEFORE_TIME; + hx509_clear_error_string(context); + goto out; + } + t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter); + if (t < ctx->time_now) { + ret = HX509_CERT_USED_AFTER_TIME; + hx509_clear_error_string(context); + goto out; + } + } + + if (type == EE_CERT) + type = CA_CERT; + else if (type == PROXY_CERT) + proxy_cert_depth++; + } + + /* + * Verify constraints, do this backward so path constraints are + * checked in the right order. + */ + + for (ret = 0, k = path.len; k > 0; k--) { + Certificate *c; + int selfsigned; + i = k - 1; + + c = _hx509_get_cert(path.val[i]); + + ret = certificate_is_self_signed(context, c, &selfsigned); + if (ret) + goto out; + + /* verify name constraints, not for selfsigned and anchor */ + if (!selfsigned || i + 1 != path.len) { + ret = check_name_constraints(context, &nc, c); + if (ret) { + goto out; + } + } + ret = add_name_constraints(context, c, i == 0, &nc); + if (ret) + goto out; + + /* XXX verify all other silly constraints */ + + } + + /* + * Verify that no certificates has been revoked. + */ + + if (ctx->revoke_ctx) { + hx509_certs certs; + + ret = hx509_certs_init(context, "MEMORY:revoke-certs", 0, + NULL, &certs); + if (ret) + goto out; + + for (i = 0; i < path.len; i++) { + ret = hx509_certs_add(context, certs, path.val[i]); + if (ret) { + hx509_certs_free(&certs); + goto out; + } + } + ret = hx509_certs_merge(context, certs, pool); + if (ret) { + hx509_certs_free(&certs); + goto out; + } + + for (i = 0; i < path.len - 1; i++) { + size_t parent = (i < path.len - 1) ? i + 1 : i; + + ret = hx509_revoke_verify(context, + ctx->revoke_ctx, + certs, + ctx->time_now, + path.val[i], + path.val[parent]); + if (ret) { + hx509_certs_free(&certs); + goto out; + } + } + hx509_certs_free(&certs); + } + + /* + * Verify signatures, do this backward so public key working + * parameter is passed up from the anchor up though the chain. + */ + + for (k = path.len; k > 0; k--) { + hx509_cert signer; + Certificate *c; + i = k - 1; + + c = _hx509_get_cert(path.val[i]); + + /* is last in chain (trust anchor) */ + if (i + 1 == path.len) { + int selfsigned; + + signer = path.val[i]; + + ret = certificate_is_self_signed(context, signer->data, &selfsigned); + if (ret) + goto out; + + /* if trust anchor is not self signed, don't check sig */ + if (!selfsigned) + continue; + } else { + /* take next certificate in chain */ + signer = path.val[i + 1]; + } + + /* verify signatureValue */ + ret = _hx509_verify_signature_bitstring(context, + signer, + &c->signatureAlgorithm, + &c->tbsCertificate._save, + &c->signatureValue); + if (ret) { + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + "Failed to verify signature of certificate"); + goto out; + } + /* + * Verify that the sigature algorithm is not weak. Ignore + * trust anchors since they are provisioned by the user. + */ + + if (i + 1 != path.len && (ctx->flags & HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK) == 0) { + ret = _hx509_signature_is_weak(context, &c->signatureAlgorithm); + if (ret) + goto out; + } + } + +out: + hx509_certs_free(&anchors); + free_Name(&proxy_issuer); + free_name_constraints(&nc); + _hx509_path_free(&path); + + return ret; +} + +/** + * Verify a signature made using the private key of an certificate. + * + * @param context A hx509 context. + * @param signer the certificate that made the signature. + * @param alg algorthm that was used to sign the data. + * @param data the data that was signed. + * @param sig the sigature to verify. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_crypto + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_verify_signature(hx509_context context, + const hx509_cert signer, + const AlgorithmIdentifier *alg, + const heim_octet_string *data, + const heim_octet_string *sig) +{ + return _hx509_verify_signature(context, signer, alg, data, sig); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_verify_signature_bitstring(hx509_context context, + const hx509_cert signer, + const AlgorithmIdentifier *alg, + const heim_octet_string *data, + const heim_bit_string *sig) +{ + heim_octet_string os; + + if (sig->length & 7) { + hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, + "signature not multiple of 8 bits"); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + + os.data = sig->data; + os.length = sig->length / 8; + + return _hx509_verify_signature(context, signer, alg, data, &os); +} + + + +/** + * Verify that the certificate is allowed to be used for the hostname + * and address. + * + * @param context A hx509 context. + * @param cert the certificate to match with + * @param flags Flags to modify the behavior: + * - HX509_VHN_F_ALLOW_NO_MATCH no match is ok + * @param type type of hostname: + * - HX509_HN_HOSTNAME for plain hostname. + * - HX509_HN_DNSSRV for DNS SRV names. + * @param hostname the hostname to check + * @param sa address of the host + * @param sa_size length of address + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_verify_hostname(hx509_context context, + const hx509_cert cert, + int flags, + hx509_hostname_type type, + const char *hostname, + const struct sockaddr *sa, + /* XXX krb5_socklen_t */ int sa_size) +{ + GeneralNames san; + const Name *name; + int ret; + size_t i, j, k; + + if (sa && sa_size <= 0) + return EINVAL; + + memset(&san, 0, sizeof(san)); + + i = 0; + do { + ret = find_extension_subject_alt_name(cert->data, &i, &san); + if (ret == HX509_EXTENSION_NOT_FOUND) + break; + else if (ret != 0) + return HX509_PARSING_NAME_FAILED; + + for (j = 0; j < san.len; j++) { + switch (san.val[j].element) { + case choice_GeneralName_dNSName: { + heim_printable_string hn; + hn.data = rk_UNCONST(hostname); + hn.length = strlen(hostname); + + if (der_printable_string_cmp(&san.val[j].u.dNSName, &hn) == 0) { + free_GeneralNames(&san); + return 0; + } + break; + } + default: + break; + } + } + free_GeneralNames(&san); + } while (1); + + name = &cert->data->tbsCertificate.subject; + + /* Find first CN= in the name, and try to match the hostname on that */ + for (ret = 0, k = name->u.rdnSequence.len; ret == 0 && k > 0; k--) { + i = k - 1; + for (j = 0; ret == 0 && j < name->u.rdnSequence.val[i].len; j++) { + AttributeTypeAndValue *n = &name->u.rdnSequence.val[i].val[j]; + + if (der_heim_oid_cmp(&n->type, &asn1_oid_id_at_commonName) == 0) { + DirectoryString *ds = &n->value; + switch (ds->element) { + case choice_DirectoryString_printableString: { + heim_printable_string hn; + hn.data = rk_UNCONST(hostname); + hn.length = strlen(hostname); + + if (der_printable_string_cmp(&ds->u.printableString, &hn) == 0) + return 0; + break; + } + case choice_DirectoryString_ia5String: { + heim_ia5_string hn; + hn.data = rk_UNCONST(hostname); + hn.length = strlen(hostname); + + if (der_ia5_string_cmp(&ds->u.ia5String, &hn) == 0) + return 0; + break; + } + case choice_DirectoryString_utf8String: + if (strcasecmp(ds->u.utf8String, hostname) == 0) + return 0; + default: + break; + } + ret = HX509_NAME_CONSTRAINT_ERROR; + } + } + } + + if ((flags & HX509_VHN_F_ALLOW_NO_MATCH) == 0) + ret = HX509_NAME_CONSTRAINT_ERROR; + + return ret; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_set_cert_attribute(hx509_context context, + hx509_cert cert, + const heim_oid *oid, + const heim_octet_string *attr) +{ + hx509_cert_attribute a; + void *d; + int ret; + + /* + * TODO: Rewrite this (and hx509_cert_attribute, and _hx509_cert_attrs) to + * use the add_AttributeValues() util generated by asn1_compile. + */ + + if (hx509_cert_get_attribute(cert, oid) != NULL) + return 0; + + d = realloc(cert->attrs.val, + sizeof(cert->attrs.val[0]) * (cert->attrs.len + 1)); + if (d == NULL) { + hx509_clear_error_string(context); + return ENOMEM; + } + cert->attrs.val = d; + + a = malloc(sizeof(*a)); + if (a == NULL) + return ENOMEM; + + ret = der_copy_octet_string(attr, &a->data); + if (ret == 0) + ret = der_copy_oid(oid, &a->oid); + if (ret == 0) { + cert->attrs.val[cert->attrs.len] = a; + cert->attrs.len++; + } else { + der_free_octet_string(&a->data); + free(a); + } + + return ret; +} + +/** + * Get an external attribute for the certificate, examples are + * friendly name and id. + * + * @param cert hx509 certificate object to search + * @param oid an oid to search for. + * + * @return an hx509_cert_attribute, only valid as long as the + * certificate is referenced. + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION hx509_cert_attribute HX509_LIB_CALL +hx509_cert_get_attribute(hx509_cert cert, const heim_oid *oid) +{ + size_t i; + for (i = 0; i < cert->attrs.len; i++) + if (der_heim_oid_cmp(oid, &cert->attrs.val[i]->oid) == 0) + return cert->attrs.val[i]; + return NULL; +} + +/** + * Set the friendly name on the certificate. + * + * @param cert The certificate to set the friendly name on + * @param name Friendly name. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cert_set_friendly_name(hx509_cert cert, const char *name) +{ + if (cert->friendlyname) + free(cert->friendlyname); + cert->friendlyname = strdup(name); + if (cert->friendlyname == NULL) + return ENOMEM; + return 0; +} + +/** + * Get friendly name of the certificate. + * + * @param cert cert to get the friendly name from. + * + * @return an friendly name or NULL if there is. The friendly name is + * only valid as long as the certificate is referenced. + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION const char * HX509_LIB_CALL +hx509_cert_get_friendly_name(hx509_cert cert) +{ + hx509_cert_attribute a; + PKCS9_friendlyName n; + size_t sz; + int ret; + size_t i; + + if (cert->friendlyname) + return cert->friendlyname; + + a = hx509_cert_get_attribute(cert, &asn1_oid_id_pkcs_9_at_friendlyName); + if (a == NULL) { + hx509_name name; + + ret = hx509_cert_get_subject(cert, &name); + if (ret) + return NULL; + ret = hx509_name_to_string(name, &cert->friendlyname); + hx509_name_free(&name); + if (ret) + return NULL; + return cert->friendlyname; + } + + ret = decode_PKCS9_friendlyName(a->data.data, a->data.length, &n, &sz); + if (ret) + return NULL; + + if (n.len != 1) { + free_PKCS9_friendlyName(&n); + return NULL; + } + + cert->friendlyname = malloc(n.val[0].length + 1); + if (cert->friendlyname == NULL) { + free_PKCS9_friendlyName(&n); + return NULL; + } + + for (i = 0; i < n.val[0].length; i++) { + if (n.val[0].data[i] <= 0xff) + cert->friendlyname[i] = n.val[0].data[i] & 0xff; + else + cert->friendlyname[i] = 'X'; + } + cert->friendlyname[i] = '\0'; + free_PKCS9_friendlyName(&n); + + return cert->friendlyname; +} + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_query_clear(hx509_query *q) +{ + memset(q, 0, sizeof(*q)); +} + +/** + * Allocate an query controller. Free using hx509_query_free(). + * + * @param context A hx509 context. + * @param q return pointer to a hx509_query. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_query_alloc(hx509_context context, hx509_query **q) +{ + *q = calloc(1, sizeof(**q)); + if (*q == NULL) + return ENOMEM; + return 0; +} + + +/** + * Set match options for the hx509 query controller. + * + * @param q query controller. + * @param option options to control the query controller. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_query_match_option(hx509_query *q, hx509_query_option option) +{ + switch(option) { + case HX509_QUERY_OPTION_PRIVATE_KEY: + q->match |= HX509_QUERY_PRIVATE_KEY; + break; + case HX509_QUERY_OPTION_KU_ENCIPHERMENT: + q->match |= HX509_QUERY_KU_ENCIPHERMENT; + break; + case HX509_QUERY_OPTION_KU_DIGITALSIGNATURE: + q->match |= HX509_QUERY_KU_DIGITALSIGNATURE; + break; + case HX509_QUERY_OPTION_KU_KEYCERTSIGN: + q->match |= HX509_QUERY_KU_KEYCERTSIGN; + break; + case HX509_QUERY_OPTION_END: + default: + break; + } +} + +/** + * Set the issuer and serial number of match in the query + * controller. The function make copies of the isser and serial number. + * + * @param q a hx509 query controller + * @param issuer issuer to search for + * @param serialNumber the serialNumber of the issuer. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_query_match_issuer_serial(hx509_query *q, + const Name *issuer, + const heim_integer *serialNumber) +{ + int ret; + if (q->serial) { + der_free_heim_integer(q->serial); + free(q->serial); + } + q->serial = malloc(sizeof(*q->serial)); + if (q->serial == NULL) + return ENOMEM; + ret = der_copy_heim_integer(serialNumber, q->serial); + if (ret) { + free(q->serial); + q->serial = NULL; + return ret; + } + if (q->issuer_name) { + free_Name(q->issuer_name); + free(q->issuer_name); + } + q->issuer_name = malloc(sizeof(*q->issuer_name)); + if (q->issuer_name == NULL) + return ENOMEM; + ret = copy_Name(issuer, q->issuer_name); + if (ret) { + free(q->issuer_name); + q->issuer_name = NULL; + return ret; + } + q->match |= HX509_QUERY_MATCH_SERIALNUMBER|HX509_QUERY_MATCH_ISSUER_NAME; + return 0; +} + +/** + * Set the query controller to match on a friendly name + * + * @param q a hx509 query controller. + * @param name a friendly name to match on + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_query_match_friendly_name(hx509_query *q, const char *name) +{ + if (q->friendlyname) + free(q->friendlyname); + q->friendlyname = strdup(name); + if (q->friendlyname == NULL) + return ENOMEM; + q->match |= HX509_QUERY_MATCH_FRIENDLY_NAME; + return 0; +} + +/** + * Set the query controller to require an one specific EKU (extended + * key usage). Any previous EKU matching is overwitten. If NULL is + * passed in as the eku, the EKU requirement is reset. + * + * @param q a hx509 query controller. + * @param eku an EKU to match on. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_query_match_eku(hx509_query *q, const heim_oid *eku) +{ + int ret; + + if (eku == NULL) { + if (q->eku) { + der_free_oid(q->eku); + free(q->eku); + q->eku = NULL; + } + q->match &= ~HX509_QUERY_MATCH_EKU; + } else { + if (q->eku) { + der_free_oid(q->eku); + } else { + q->eku = calloc(1, sizeof(*q->eku)); + if (q->eku == NULL) + return ENOMEM; + } + ret = der_copy_oid(eku, q->eku); + if (ret) { + free(q->eku); + q->eku = NULL; + return ret; + } + q->match |= HX509_QUERY_MATCH_EKU; + } + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_query_match_expr(hx509_context context, hx509_query *q, const char *expr) +{ + if (q->expr) { + _hx509_expr_free(q->expr); + q->expr = NULL; + } + + if (expr == NULL) { + q->match &= ~HX509_QUERY_MATCH_EXPR; + return 0; + } + + q->expr = _hx509_expr_parse(expr); + if (q->expr == NULL) { + const char *reason = _hx509_expr_parse_error(); + + hx509_set_error_string(context, 0, EINVAL, + "Invalid certificate query match expression: " + "%s (%s)", expr, + reason ? reason : "syntax error"); + return EINVAL; + } + + q->match |= HX509_QUERY_MATCH_EXPR; + return 0; +} + +/** + * Set the query controller to match using a specific match function. + * + * @param q a hx509 query controller. + * @param func function to use for matching, if the argument is NULL, + * the match function is removed. + * @param ctx context passed to the function. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_query_match_cmp_func(hx509_query *q, + int (*func)(hx509_context, hx509_cert, void *), + void *ctx) +{ + if (func) + q->match |= HX509_QUERY_MATCH_FUNCTION; + else + q->match &= ~HX509_QUERY_MATCH_FUNCTION; + q->cmp_func = func; + q->cmp_func_ctx = ctx; + return 0; +} + +/** + * Free the query controller. + * + * @param context A hx509 context. + * @param q a pointer to the query controller. + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_query_free(hx509_context context, hx509_query *q) +{ + if (q == NULL) + return; + + if (q->serial) { + der_free_heim_integer(q->serial); + free(q->serial); + } + if (q->issuer_name) { + free_Name(q->issuer_name); + free(q->issuer_name); + } + if (q->eku) { + der_free_oid(q->eku); + free(q->eku); + } + if (q->friendlyname) + free(q->friendlyname); + if (q->expr) + _hx509_expr_free(q->expr); + + memset(q, 0, sizeof(*q)); + free(q); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert cert) +{ + Certificate *c = _hx509_get_cert(cert); + int ret, diff; + + _hx509_query_statistic(context, 1, q); + + if ((q->match & HX509_QUERY_FIND_ISSUER_CERT) && + _hx509_cert_is_parent_cmp(q->subject, c, 0) != 0) + return 0; + + if ((q->match & HX509_QUERY_MATCH_CERTIFICATE) && + _hx509_Certificate_cmp(q->certificate, c) != 0) + return 0; + + if ((q->match & HX509_QUERY_MATCH_SERIALNUMBER) + && der_heim_integer_cmp(&c->tbsCertificate.serialNumber, q->serial) != 0) + return 0; + + if (q->match & HX509_QUERY_MATCH_ISSUER_NAME) { + ret = _hx509_name_cmp(&c->tbsCertificate.issuer, q->issuer_name, &diff); + if (ret || diff) + return 0; + } + + if (q->match & HX509_QUERY_MATCH_SUBJECT_NAME) { + ret = _hx509_name_cmp(&c->tbsCertificate.subject, q->subject_name, &diff); + if (ret || diff) + return 0; + } + + if (q->match & HX509_QUERY_MATCH_SUBJECT_KEY_ID) { + SubjectKeyIdentifier si; + + ret = _hx509_find_extension_subject_key_id(c, &si); + if (ret == 0) { + if (der_heim_octet_string_cmp(&si, q->subject_id) != 0) + ret = 1; + free_SubjectKeyIdentifier(&si); + } + if (ret) + return 0; + } + if ((q->match & HX509_QUERY_MATCH_ISSUER_ID)) + return 0; + if ((q->match & HX509_QUERY_PRIVATE_KEY) && + _hx509_cert_private_key(cert) == NULL) + return 0; + + { + unsigned ku = 0; + if (q->match & HX509_QUERY_KU_DIGITALSIGNATURE) + ku |= (1 << 0); + if (q->match & HX509_QUERY_KU_NONREPUDIATION) + ku |= (1 << 1); + if (q->match & HX509_QUERY_KU_ENCIPHERMENT) + ku |= (1 << 2); + if (q->match & HX509_QUERY_KU_DATAENCIPHERMENT) + ku |= (1 << 3); + if (q->match & HX509_QUERY_KU_KEYAGREEMENT) + ku |= (1 << 4); + if (q->match & HX509_QUERY_KU_KEYCERTSIGN) + ku |= (1 << 5); + if (q->match & HX509_QUERY_KU_CRLSIGN) + ku |= (1 << 6); + if (ku && check_key_usage(context, c, ku, TRUE)) + return 0; + } + if ((q->match & HX509_QUERY_ANCHOR)) + return 0; + + if (q->match & HX509_QUERY_MATCH_LOCAL_KEY_ID) { + hx509_cert_attribute a; + + a = hx509_cert_get_attribute(cert, &asn1_oid_id_pkcs_9_at_localKeyId); + if (a == NULL) + return 0; + if (der_heim_octet_string_cmp(&a->data, q->local_key_id) != 0) + return 0; + } + + if (q->match & HX509_QUERY_NO_MATCH_PATH) { + size_t i; + + for (i = 0; i < q->path->len; i++) + if (hx509_cert_cmp(q->path->val[i], cert) == 0) + return 0; + } + if (q->match & HX509_QUERY_MATCH_FRIENDLY_NAME) { + const char *name = hx509_cert_get_friendly_name(cert); + if (name == NULL) + return 0; + if (strcasecmp(q->friendlyname, name) != 0) + return 0; + } + if (q->match & HX509_QUERY_MATCH_FUNCTION) { + ret = (*q->cmp_func)(context, cert, q->cmp_func_ctx); + if (ret != 0) + return 0; + } + + if (q->match & HX509_QUERY_MATCH_KEY_HASH_SHA1) { + heim_octet_string os; + + os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data; + os.length = + c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8; + + ret = _hx509_verify_signature(context, + NULL, + hx509_signature_sha1(), + &os, + q->keyhash_sha1); + if (ret != 0) + return 0; + } + + if (q->match & HX509_QUERY_MATCH_TIME) { + time_t t; + t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore); + if (t > q->timenow) + return 0; + t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter); + if (t < q->timenow) + return 0; + } + + /* If an EKU is required, check the cert for it. */ + if ((q->match & HX509_QUERY_MATCH_EKU) && + hx509_cert_check_eku(context, cert, q->eku, 0)) + return 0; + + if ((q->match & HX509_QUERY_MATCH_EXPR)) { + hx509_env env = NULL; + + ret = _hx509_cert_to_env(context, cert, &env); + if (ret) + return 0; + + ret = _hx509_expr_eval(context, env, q->expr); + hx509_env_free(&env); + if (ret == 0) + return 0; + } + + if (q->match & ~HX509_QUERY_MASK) + return 0; + + return 1; +} + +/** + * Set a statistic file for the query statistics. + * + * @param context A hx509 context. + * @param fn statistics file name + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_query_statistic_file(hx509_context context, const char *fn) +{ + if (context->querystat) + free(context->querystat); + context->querystat = strdup(fn); +} + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_query_statistic(hx509_context context, int type, const hx509_query *q) +{ + FILE *f; + if (context->querystat == NULL) + return; + f = fopen(context->querystat, "a"); + if (f == NULL) + return; + rk_cloexec_file(f); + fprintf(f, "%d %d\n", type, q->match); + fclose(f); +} + +static const char *statname[] = { + "find issuer cert", + "match serialnumber", + "match issuer name", + "match subject name", + "match subject key id", + "match issuer id", + "private key", + "ku encipherment", + "ku digitalsignature", + "ku keycertsign", + "ku crlsign", + "ku nonrepudiation", + "ku keyagreement", + "ku dataencipherment", + "anchor", + "match certificate", + "match local key id", + "no match path", + "match friendly name", + "match function", + "match key hash sha1", + "match time" +}; + +struct stat_el { + unsigned long stats; + unsigned int index; +}; + + +static int +stat_sort(const void *a, const void *b) +{ + const struct stat_el *ae = a; + const struct stat_el *be = b; + return be->stats - ae->stats; +} + +/** + * Unparse the statistics file and print the result on a FILE descriptor. + * + * @param context A hx509 context. + * @param printtype tyep to print + * @param out the FILE to write the data on. + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_query_unparse_stats(hx509_context context, int printtype, FILE *out) +{ + rtbl_t t; + FILE *f; + int type, mask, num; + size_t i; + unsigned long multiqueries = 0, totalqueries = 0; + struct stat_el stats[32]; + + if (context->querystat == NULL) + return; + f = fopen(context->querystat, "r"); + if (f == NULL) { + fprintf(out, "No statistics file %s: %s.\n", + context->querystat, strerror(errno)); + return; + } + rk_cloexec_file(f); + + for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) { + stats[i].index = i; + stats[i].stats = 0; + } + + while (fscanf(f, "%d %d\n", &type, &mask) == 2) { + if (type != printtype) + continue; + num = i = 0; + while (mask && i < sizeof(stats)/sizeof(stats[0])) { + if (mask & 1) { + stats[i].stats++; + num++; + } + mask = mask >>1 ; + i++; + } + if (num > 1) + multiqueries++; + totalqueries++; + } + fclose(f); + + qsort(stats, sizeof(stats)/sizeof(stats[0]), sizeof(stats[0]), stat_sort); + + t = rtbl_create(); + if (t == NULL) + errx(1, "out of memory"); + + rtbl_set_separator (t, " "); + + rtbl_add_column_by_id (t, 0, "Name", 0); + rtbl_add_column_by_id (t, 1, "Counter", 0); + + + for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) { + char str[10]; + + if (stats[i].index < sizeof(statname)/sizeof(statname[0])) + rtbl_add_column_entry_by_id (t, 0, statname[stats[i].index]); + else { + snprintf(str, sizeof(str), "%d", stats[i].index); + rtbl_add_column_entry_by_id (t, 0, str); + } + snprintf(str, sizeof(str), "%lu", stats[i].stats); + rtbl_add_column_entry_by_id (t, 1, str); + } + + rtbl_format(t, out); + rtbl_destroy(t); + + fprintf(out, "\nQueries: multi %lu total %lu\n", + multiqueries, totalqueries); +} + +/** + * Check the extended key usage on the hx509 certificate. + * + * @param context A hx509 context. + * @param cert A hx509 context. + * @param eku the EKU to check for + * @param allow_any_eku if the any EKU is set, allow that to be a + * substitute. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cert_check_eku(hx509_context context, hx509_cert cert, + const heim_oid *eku, int allow_any_eku) +{ + ExtKeyUsage e; + int ret; + size_t i; + + ret = find_extension_eku(_hx509_get_cert(cert), &e); + if (ret) { + hx509_clear_error_string(context); + return ret; + } + + for (i = 0; i < e.len; i++) { + if (der_heim_oid_cmp(eku, &e.val[i]) == 0) { + free_ExtKeyUsage(&e); + return 0; + } + if (allow_any_eku) { + if (der_heim_oid_cmp(&asn1_oid_id_x509_ce_anyExtendedKeyUsage, + &e.val[i]) == 0) { + free_ExtKeyUsage(&e); + return 0; + } + } + } + free_ExtKeyUsage(&e); + hx509_clear_error_string(context); + return HX509_CERTIFICATE_MISSING_EKU; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_cert_get_keyusage(hx509_context context, + hx509_cert c, + KeyUsage *ku) +{ + Certificate *cert; + const Extension *e; + size_t size; + int ret; + size_t i = 0; + + memset(ku, 0, sizeof(*ku)); + + cert = _hx509_get_cert(c); + + if (_hx509_cert_get_version(cert) < 3) + return 0; + + e = find_extension(cert, &asn1_oid_id_x509_ce_keyUsage, &i); + if (e == NULL) + return HX509_KU_CERT_MISSING; + + ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, ku, &size); + if (ret) + return ret; + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_cert_get_eku(hx509_context context, + hx509_cert cert, + ExtKeyUsage *e) +{ + int ret; + + memset(e, 0, sizeof(*e)); + + ret = find_extension_eku(_hx509_get_cert(cert), e); + if (ret && ret != HX509_EXTENSION_NOT_FOUND) { + hx509_clear_error_string(context); + return ret; + } + return 0; +} + +/** + * Encodes the hx509 certificate as a DER encode binary. + * + * @param context A hx509 context. + * @param c the certificate to encode. + * @param os the encode certificate, set to NULL, 0 on case of + * error. Free the os->data with hx509_xfree(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cert_binary(hx509_context context, hx509_cert c, heim_octet_string *os) +{ + size_t size; + int ret; + + os->data = NULL; + os->length = 0; + + ASN1_MALLOC_ENCODE(Certificate, os->data, os->length, + _hx509_get_cert(c), &size, ret); + if (ret) { + os->data = NULL; + os->length = 0; + return ret; + } + if (os->length != size) + _hx509_abort("internal ASN.1 encoder error"); + return ret; +} + +/* + * Last to avoid lost __attribute__s due to #undef. + */ + +#undef __attribute__ +#define __attribute__(X) + +HX509_LIB_NORETURN_FUNCTION void HX509_LIB_CALL +_hx509_abort(const char *fmt, ...) + __attribute__ ((__noreturn__, __format__ (__printf__, 1, 2))) +{ + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf("\n"); + fflush(stdout); + abort(); +} + +/** + * Free a data element allocated in the library. + * + * @param ptr data to be freed. + * + * @ingroup hx509_misc + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_xfree(void *ptr) +{ + free(ptr); +} + +/** + * + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_cert_to_env(hx509_context context, hx509_cert cert, hx509_env *env) +{ + ExtKeyUsage eku; + hx509_name name; + char *buf; + int ret; + hx509_env envcert = NULL; + + *env = NULL; + + /* version */ + ret = asprintf(&buf, "%d", _hx509_cert_get_version(_hx509_get_cert(cert))); + if (ret == -1) + goto out; + ret = hx509_env_add(context, &envcert, "version", buf); + free(buf); + if (ret) + goto out; + + /* subject */ + ret = hx509_cert_get_subject(cert, &name); + if (ret) + goto out; + + ret = hx509_name_to_string(name, &buf); + hx509_name_free(&name); + if (ret) + goto out; + + ret = hx509_env_add(context, &envcert, "subject", buf); + hx509_xfree(buf); + if (ret) + goto out; + + /* issuer */ + ret = hx509_cert_get_issuer(cert, &name); + if (ret) + goto out; + + ret = hx509_name_to_string(name, &buf); + hx509_name_free(&name); + if (ret) + goto out; + + ret = hx509_env_add(context, &envcert, "issuer", buf); + hx509_xfree(buf); + if (ret) + goto out; + + /* eku */ + + ret = _hx509_cert_get_eku(context, cert, &eku); + if (ret == HX509_EXTENSION_NOT_FOUND) + ; + else if (ret != 0) + goto out; + else { + size_t i; + hx509_env enveku = NULL; + + for (i = 0; i < eku.len; i++) { + + ret = der_print_heim_oid(&eku.val[i], '.', &buf); + if (ret) { + free_ExtKeyUsage(&eku); + hx509_env_free(&enveku); + goto out; + } + ret = hx509_env_add(context, &enveku, buf, "oid-name-here"); + free(buf); + if (ret) { + free_ExtKeyUsage(&eku); + hx509_env_free(&enveku); + goto out; + } + } + free_ExtKeyUsage(&eku); + + ret = hx509_env_add_binding(context, &envcert, "eku", enveku); + if (ret) { + hx509_env_free(&enveku); + goto out; + } + } + + { + Certificate *c = _hx509_get_cert(cert); + heim_octet_string os, sig; + hx509_env envhash = NULL; + + os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data; + os.length = + c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8; + + ret = _hx509_create_signature(context, + NULL, + hx509_signature_sha1(), + &os, + NULL, + &sig); + if (ret != 0) + goto out; + + ret = hex_encode(sig.data, sig.length, &buf); + der_free_octet_string(&sig); + if (ret < 0) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, + "Out of memory"); + goto out; + } + + ret = hx509_env_add(context, &envhash, "sha1", buf); + free(buf); + if (ret) + goto out; + + ret = hx509_env_add_binding(context, &envcert, "hash", envhash); + if (ret) { + hx509_env_free(&envhash); + goto out; + } + } + + ret = hx509_env_add_binding(context, env, "certificate", envcert); + if (ret) + goto out; + + return 0; + +out: + hx509_env_free(&envcert); + return ret; +} + +/** + * Print a simple representation of a certificate + * + * @param context A hx509 context, can be NULL + * @param cert certificate to print + * @param out the stdio output stream, if NULL, stdout is used + * + * @return An hx509 error code + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_print_cert(hx509_context context, hx509_cert cert, FILE *out) +{ + hx509_name name; + char *str; + int ret; + + if (out == NULL) + out = stderr; + + ret = hx509_cert_get_issuer(cert, &name); + if (ret) + return ret; + hx509_name_to_string(name, &str); + hx509_name_free(&name); + fprintf(out, " issuer: \"%s\"\n", str); + free(str); + + ret = hx509_cert_get_subject(cert, &name); + if (ret) + return ret; + hx509_name_to_string(name, &str); + hx509_name_free(&name); + fprintf(out, " subject: \"%s\"\n", str); + free(str); + + { + heim_integer serialNumber; + + ret = hx509_cert_get_serialnumber(cert, &serialNumber); + if (ret) + return ret; + ret = der_print_hex_heim_integer(&serialNumber, &str); + if (ret) + return ret; + der_free_heim_integer(&serialNumber); + fprintf(out, " serial: %s\n", str); + free(str); + } + + fprintf(out, " keyusage: "); + ret = hx509_cert_keyusage_print(context, cert, &str); + if (ret == 0) { + fprintf(out, "%s\n", str); + free(str); + } else + fprintf(out, "no"); + + return 0; +} diff --git a/third_party/heimdal/lib/hx509/char_map.h b/third_party/heimdal/lib/hx509/char_map.h new file mode 100644 index 0000000..8a3026c --- /dev/null +++ b/third_party/heimdal/lib/hx509/char_map.h @@ -0,0 +1,45 @@ +#define Q_CONTROL_CHAR 1 +#define Q_PRINTABLE 2 +#define Q_RFC2253_QUOTE_FIRST 4 +#define Q_RFC2253_QUOTE_LAST 8 +#define Q_RFC2253_QUOTE 16 +#define Q_RFC2253_HEX 32 + +#define Q_RFC2253 (Q_RFC2253_QUOTE_FIRST|Q_RFC2253_QUOTE_LAST|Q_RFC2253_QUOTE|Q_RFC2253_HEX) + + + +unsigned char char_map[] = { + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x06 , 0x00 , 0x00 , 0x10 , 0x00 , 0x00 , 0x00 , 0x00 , + 0x00 , 0x00 , 0x00 , 0x12 , 0x12 , 0x02 , 0x02 , 0x02 , + 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , + 0x02 , 0x02 , 0x02 , 0x10 , 0x10 , 0x12 , 0x10 , 0x02 , + 0x00 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , + 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , + 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , + 0x02 , 0x02 , 0x02 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , + 0x00 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , + 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , + 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , + 0x02 , 0x02 , 0x02 , 0x00 , 0x00 , 0x00 , 0x00 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 +}; diff --git a/third_party/heimdal/lib/hx509/cms.c b/third_party/heimdal/lib/hx509/cms.c new file mode 100644 index 0000000..d2728a3 --- /dev/null +++ b/third_party/heimdal/lib/hx509/cms.c @@ -0,0 +1,1718 @@ +/* + * Copyright (c) 2003 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" + +/** + * @page page_cms CMS/PKCS7 message functions. + * + * CMS is defined in RFC 3369 and is an continuation of the RSA Labs + * standard PKCS7. The basic messages in CMS is + * + * - SignedData + * Data signed with private key (RSA, DSA, ECDSA) or secret + * (symmetric) key + * - EnvelopedData + * Data encrypted with private key (RSA) + * - EncryptedData + * Data encrypted with secret (symmetric) key. + * - ContentInfo + * Wrapper structure including type and data. + * + * + * See the library functions here: @ref hx509_cms + */ + +#define ALLOC(X, N) (X) = calloc((N), sizeof(*(X))) +#define ALLOC_SEQ(X, N) do { (X)->len = (N); ALLOC((X)->val, (N)); } while(0) + +/** + * Wrap data and oid in a ContentInfo and encode it. + * + * @param oid type of the content. + * @param buf data to be wrapped. If a NULL pointer is passed in, the + * optional content field in the ContentInfo is not going be filled + * in. + * @param res the encoded buffer, the result should be freed with + * der_free_octet_string(). + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_cms + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cms_wrap_ContentInfo(const heim_oid *oid, + const heim_octet_string *buf, + heim_octet_string *res) +{ + ContentInfo ci; + size_t size; + int ret; + + memset(res, 0, sizeof(*res)); + memset(&ci, 0, sizeof(ci)); + + ret = der_copy_oid(oid, &ci.contentType); + if (ret) + return ret; + if (buf) { + ALLOC(ci.content, 1); + if (ci.content == NULL) { + free_ContentInfo(&ci); + return ENOMEM; + } + ci.content->data = malloc(buf->length); + if (ci.content->data == NULL) { + free_ContentInfo(&ci); + return ENOMEM; + } + memcpy(ci.content->data, buf->data, buf->length); + ci.content->length = buf->length; + } + + ASN1_MALLOC_ENCODE(ContentInfo, res->data, res->length, &ci, &size, ret); + free_ContentInfo(&ci); + if (ret) + return ret; + if (res->length != size) + _hx509_abort("internal ASN.1 encoder error"); + + return 0; +} + +/** + * Decode an ContentInfo and unwrap data and oid it. + * + * @param in the encoded buffer. + * @param oid type of the content. + * @param out data to be wrapped. + * @param have_data since the data is optional, this flags show dthe + * diffrence between no data and the zero length data. + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_cms + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cms_unwrap_ContentInfo(const heim_octet_string *in, + heim_oid *oid, + heim_octet_string *out, + int *have_data) +{ + ContentInfo ci; + size_t size; + int ret; + + memset(oid, 0, sizeof(*oid)); + memset(out, 0, sizeof(*out)); + + ret = decode_ContentInfo(in->data, in->length, &ci, &size); + if (ret) + return ret; + + ret = der_copy_oid(&ci.contentType, oid); + if (ret) { + free_ContentInfo(&ci); + return ret; + } + if (ci.content) { + ret = der_copy_octet_string(ci.content, out); + if (ret) { + der_free_oid(oid); + free_ContentInfo(&ci); + return ret; + } + } else + memset(out, 0, sizeof(*out)); + + if (have_data) + *have_data = (ci.content != NULL) ? 1 : 0; + + free_ContentInfo(&ci); + + return 0; +} + +#define CMS_ID_SKI 0 +#define CMS_ID_NAME 1 + +static int +fill_CMSIdentifier(const hx509_cert cert, + int type, + CMSIdentifier *id) +{ + int ret; + + switch (type) { + case CMS_ID_SKI: + id->element = choice_CMSIdentifier_subjectKeyIdentifier; + ret = _hx509_find_extension_subject_key_id(_hx509_get_cert(cert), + &id->u.subjectKeyIdentifier); + if (ret == 0) + break; + fallthrough; + case CMS_ID_NAME: { + hx509_name name; + + id->element = choice_CMSIdentifier_issuerAndSerialNumber; + ret = hx509_cert_get_issuer(cert, &name); + if (ret) + return ret; + ret = hx509_name_to_Name(name, &id->u.issuerAndSerialNumber.issuer); + hx509_name_free(&name); + if (ret) + return ret; + + ret = hx509_cert_get_serialnumber(cert, &id->u.issuerAndSerialNumber.serialNumber); + break; + } + default: + _hx509_abort("CMS fill identifier with unknown type"); + } + return ret; +} + +static int +unparse_CMSIdentifier(hx509_context context, + CMSIdentifier *id, + char **str) +{ + int ret = -1; + + *str = NULL; + switch (id->element) { + case choice_CMSIdentifier_issuerAndSerialNumber: { + IssuerAndSerialNumber *iasn; + char *serial, *name; + + iasn = &id->u.issuerAndSerialNumber; + + ret = _hx509_Name_to_string(&iasn->issuer, &name); + if(ret) + return ret; + ret = der_print_hex_heim_integer(&iasn->serialNumber, &serial); + if (ret) { + free(name); + return ret; + } + ret = asprintf(str, "certificate issued by %s with serial number %s", + name, serial); + free(name); + free(serial); + break; + } + case choice_CMSIdentifier_subjectKeyIdentifier: { + KeyIdentifier *ki = &id->u.subjectKeyIdentifier; + char *keyid; + ssize_t len; + + len = hex_encode(ki->data, ki->length, &keyid); + if (len < 0) + return ENOMEM; + + ret = asprintf(str, "certificate with id %s", keyid); + free(keyid); + break; + } + default: + ret = asprintf(str, "certificate have unknown CMSidentifier type"); + break; + } + /* + * In the following if, we check ret and *str which should be returned/set + * by asprintf(3) in every branch of the switch statement. + */ + if (ret == -1 || *str == NULL) + return ENOMEM; + return 0; +} + +static int +find_CMSIdentifier(hx509_context context, + CMSIdentifier *client, + hx509_certs certs, + time_t time_now, + hx509_cert *signer_cert, + int match) +{ + hx509_query q; + hx509_cert cert; + Certificate c; + int ret; + + memset(&c, 0, sizeof(c)); + _hx509_query_clear(&q); + + *signer_cert = NULL; + + switch (client->element) { + case choice_CMSIdentifier_issuerAndSerialNumber: + q.serial = &client->u.issuerAndSerialNumber.serialNumber; + q.issuer_name = &client->u.issuerAndSerialNumber.issuer; + q.match = HX509_QUERY_MATCH_SERIALNUMBER|HX509_QUERY_MATCH_ISSUER_NAME; + break; + case choice_CMSIdentifier_subjectKeyIdentifier: + q.subject_id = &client->u.subjectKeyIdentifier; + q.match = HX509_QUERY_MATCH_SUBJECT_KEY_ID; + break; + default: + hx509_set_error_string(context, 0, HX509_CMS_NO_RECIPIENT_CERTIFICATE, + "unknown CMS identifier element"); + return HX509_CMS_NO_RECIPIENT_CERTIFICATE; + } + + q.match |= match; + + q.match |= HX509_QUERY_MATCH_TIME; + if (time_now) + q.timenow = time_now; + else + q.timenow = time(NULL); + + ret = hx509_certs_find(context, certs, &q, &cert); + if (ret == HX509_CERT_NOT_FOUND) { + char *str; + + ret = unparse_CMSIdentifier(context, client, &str); + if (ret == 0) { + hx509_set_error_string(context, 0, + HX509_CMS_NO_RECIPIENT_CERTIFICATE, + "Failed to find %s", str); + } else + hx509_clear_error_string(context); + return HX509_CMS_NO_RECIPIENT_CERTIFICATE; + } else if (ret) { + hx509_set_error_string(context, HX509_ERROR_APPEND, + HX509_CMS_NO_RECIPIENT_CERTIFICATE, + "Failed to find CMS id in cert store"); + return HX509_CMS_NO_RECIPIENT_CERTIFICATE; + } + + *signer_cert = cert; + + return 0; +} + +/** + * Decode and unencrypt EnvelopedData. + * + * Extract data and parameteres from from the EnvelopedData. Also + * supports using detached EnvelopedData. + * + * @param context A hx509 context. + * @param certs Certificate that can decrypt the EnvelopedData + * encryption key. + * @param flags HX509_CMS_UE flags to control the behavior. + * @param data pointer the structure the contains the DER/BER encoded + * EnvelopedData stucture. + * @param length length of the data that data point to. + * @param encryptedContent in case of detached signature, this + * contains the actual encrypted data, othersize its should be NULL. + * @param time_now set the current time, if zero the library uses now as the date. + * @param contentType output type oid, should be freed with der_free_oid(). + * @param content the data, free with der_free_octet_string(). + * + * @return an hx509 error code. + * + * @ingroup hx509_cms + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cms_unenvelope(hx509_context context, + hx509_certs certs, + int flags, + const void *data, + size_t length, + const heim_octet_string *encryptedContent, + time_t time_now, + heim_oid *contentType, + heim_octet_string *content) +{ + heim_octet_string key; + EnvelopedData ed; + hx509_cert cert; + AlgorithmIdentifier *ai; + const heim_octet_string *enccontent; + heim_octet_string *params, params_data; + heim_octet_string ivec; + size_t size; + int ret, matched = 0, findflags = 0; + size_t i; + + + memset(&key, 0, sizeof(key)); + memset(&ed, 0, sizeof(ed)); + memset(&ivec, 0, sizeof(ivec)); + memset(content, 0, sizeof(*content)); + memset(contentType, 0, sizeof(*contentType)); + + if ((flags & HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT) == 0) + findflags |= HX509_QUERY_KU_ENCIPHERMENT; + + ret = decode_EnvelopedData(data, length, &ed, &size); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to decode EnvelopedData"); + return ret; + } + + if (ed.recipientInfos.len == 0) { + ret = HX509_CMS_NO_RECIPIENT_CERTIFICATE; + hx509_set_error_string(context, 0, ret, + "No recipient info in enveloped data"); + goto out; + } + + enccontent = ed.encryptedContentInfo.encryptedContent; + if (enccontent == NULL) { + if (encryptedContent == NULL) { + ret = HX509_CMS_NO_DATA_AVAILABLE; + hx509_set_error_string(context, 0, ret, + "Content missing from encrypted data"); + goto out; + } + enccontent = encryptedContent; + } else if (encryptedContent != NULL) { + ret = HX509_CMS_NO_DATA_AVAILABLE; + hx509_set_error_string(context, 0, ret, + "Both internal and external encrypted data"); + goto out; + } + + cert = NULL; + for (i = 0; i < ed.recipientInfos.len; i++) { + KeyTransRecipientInfo *ri; + char *str; + int ret2; + + ri = &ed.recipientInfos.val[i]; + + ret = find_CMSIdentifier(context, &ri->rid, certs, + time_now, &cert, + HX509_QUERY_PRIVATE_KEY|findflags); + if (ret) + continue; + + matched = 1; /* found a matching certificate, let decrypt */ + + ret = _hx509_cert_private_decrypt(context, + &ri->encryptedKey, + &ri->keyEncryptionAlgorithm.algorithm, + cert, &key); + + hx509_cert_free(cert); + if (ret == 0) + break; /* succuessfully decrypted cert */ + cert = NULL; + ret2 = unparse_CMSIdentifier(context, &ri->rid, &str); + if (ret2 == 0) { + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + "Failed to decrypt with %s", str); + free(str); + } + } + + if (!matched) { + ret = HX509_CMS_NO_RECIPIENT_CERTIFICATE; + hx509_set_error_string(context, 0, ret, + "No private key matched any certificate"); + goto out; + } + + if (cert == NULL) { + ret = HX509_CMS_NO_RECIPIENT_CERTIFICATE; + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + "No private key decrypted the transfer key"); + goto out; + } + + ret = der_copy_oid(&ed.encryptedContentInfo.contentType, contentType); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to copy EnvelopedData content oid"); + goto out; + } + + ai = &ed.encryptedContentInfo.contentEncryptionAlgorithm; + if (ai->parameters) { + params_data.data = ai->parameters->data; + params_data.length = ai->parameters->length; + params = ¶ms_data; + } else + params = NULL; + + { + hx509_crypto crypto; + + ret = hx509_crypto_init(context, NULL, &ai->algorithm, &crypto); + if (ret) + goto out; + + if (flags & HX509_CMS_UE_ALLOW_WEAK) + hx509_crypto_allow_weak(crypto); + + if (params) { + ret = hx509_crypto_set_params(context, crypto, params, &ivec); + if (ret) { + hx509_crypto_destroy(crypto); + goto out; + } + } + + ret = hx509_crypto_set_key_data(crypto, key.data, key.length); + if (ret) { + hx509_crypto_destroy(crypto); + hx509_set_error_string(context, 0, ret, + "Failed to set key for decryption " + "of EnvelopedData"); + goto out; + } + + ret = hx509_crypto_decrypt(crypto, + enccontent->data, + enccontent->length, + ivec.length ? &ivec : NULL, + content); + hx509_crypto_destroy(crypto); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to decrypt EnvelopedData"); + goto out; + } + } + +out: + + free_EnvelopedData(&ed); + der_free_octet_string(&key); + if (ivec.length) + der_free_octet_string(&ivec); + if (ret) { + der_free_oid(contentType); + der_free_octet_string(content); + } + + return ret; +} + +/** + * Encrypt end encode EnvelopedData. + * + * Encrypt and encode EnvelopedData. The data is encrypted with a + * random key and the the random key is encrypted with the + * certificates private key. This limits what private key type can be + * used to RSA. + * + * @param context A hx509 context. + * @param flags flags to control the behavior. + * - HX509_CMS_EV_NO_KU_CHECK - Don't check KU on certificate + * - HX509_CMS_EV_ALLOW_WEAK - Allow weak crytpo + * - HX509_CMS_EV_ID_NAME - prefer issuer name and serial number + * @param cert Certificate to encrypt the EnvelopedData encryption key + * with. + * @param data pointer the data to encrypt. + * @param length length of the data that data point to. + * @param encryption_type Encryption cipher to use for the bulk data, + * use NULL to get default. + * @param contentType type of the data that is encrypted + * @param content the output of the function, + * free with der_free_octet_string(). + * + * @return an hx509 error code. + * + * @ingroup hx509_cms + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cms_envelope_1(hx509_context context, + int flags, + hx509_cert cert, + const void *data, + size_t length, + const heim_oid *encryption_type, + const heim_oid *contentType, + heim_octet_string *content) +{ + KeyTransRecipientInfo *ri; + heim_octet_string ivec; + heim_octet_string key; + hx509_crypto crypto = NULL; + int ret, cmsidflag; + EnvelopedData ed; + size_t size; + + memset(&ivec, 0, sizeof(ivec)); + memset(&key, 0, sizeof(key)); + memset(&ed, 0, sizeof(ed)); + memset(content, 0, sizeof(*content)); + + if (encryption_type == NULL) + encryption_type = &asn1_oid_id_aes_256_cbc; + + if ((flags & HX509_CMS_EV_NO_KU_CHECK) == 0) { + ret = _hx509_check_key_usage(context, cert, 1 << 2, TRUE); + if (ret) + goto out; + } + + ret = hx509_crypto_init(context, NULL, encryption_type, &crypto); + if (ret) + goto out; + + if (flags & HX509_CMS_EV_ALLOW_WEAK) + hx509_crypto_allow_weak(crypto); + + ret = hx509_crypto_set_random_key(crypto, &key); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Create random key for EnvelopedData content"); + goto out; + } + + ret = hx509_crypto_random_iv(crypto, &ivec); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to create a random iv"); + goto out; + } + + ret = hx509_crypto_encrypt(crypto, + data, + length, + &ivec, + &ed.encryptedContentInfo.encryptedContent); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to encrypt EnvelopedData content"); + goto out; + } + + { + AlgorithmIdentifier *enc_alg; + enc_alg = &ed.encryptedContentInfo.contentEncryptionAlgorithm; + ret = der_copy_oid(encryption_type, &enc_alg->algorithm); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to set crypto oid " + "for EnvelopedData"); + goto out; + } + ALLOC(enc_alg->parameters, 1); + if (enc_alg->parameters == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, + "Failed to allocate crypto parameters " + "for EnvelopedData"); + goto out; + } + + ret = hx509_crypto_get_params(context, + crypto, + &ivec, + enc_alg->parameters); + if (ret) { + goto out; + } + } + + ALLOC_SEQ(&ed.recipientInfos, 1); + if (ed.recipientInfos.val == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, + "Failed to allocate recipients info " + "for EnvelopedData"); + goto out; + } + + ri = &ed.recipientInfos.val[0]; + + if (flags & HX509_CMS_EV_ID_NAME) { + ri->version = 0; + cmsidflag = CMS_ID_NAME; + } else { + ri->version = 2; + cmsidflag = CMS_ID_SKI; + } + + ret = fill_CMSIdentifier(cert, cmsidflag, &ri->rid); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to set CMS identifier info " + "for EnvelopedData"); + goto out; + } + + ret = hx509_cert_public_encrypt(context, + &key, cert, + &ri->keyEncryptionAlgorithm.algorithm, + &ri->encryptedKey); + if (ret) { + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + "Failed to encrypt transport key for " + "EnvelopedData"); + goto out; + } + + /* + * + */ + + ed.version = 0; + ed.originatorInfo = NULL; + + ret = der_copy_oid(contentType, &ed.encryptedContentInfo.contentType); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to copy content oid for " + "EnvelopedData"); + goto out; + } + + ed.unprotectedAttrs = NULL; + + ASN1_MALLOC_ENCODE(EnvelopedData, content->data, content->length, + &ed, &size, ret); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to encode EnvelopedData"); + goto out; + } + if (size != content->length) + _hx509_abort("internal ASN.1 encoder error"); + +out: + if (crypto) + hx509_crypto_destroy(crypto); + if (ret) + der_free_octet_string(content); + der_free_octet_string(&key); + der_free_octet_string(&ivec); + free_EnvelopedData(&ed); + + return ret; +} + +static int +any_to_certs(hx509_context context, const SignedData *sd, hx509_certs certs) +{ + int ret; + size_t i; + + if (sd->certificates == NULL) + return 0; + + for (i = 0; i < sd->certificates->len; i++) { + heim_error_t error; + hx509_cert c; + + c = hx509_cert_init_data(context, + sd->certificates->val[i].data, + sd->certificates->val[i].length, + &error); + if (c == NULL) { + ret = heim_error_get_code(error); + heim_release(error); + return ret; + } + ret = hx509_certs_add(context, certs, c); + hx509_cert_free(c); + if (ret) + return ret; + } + + return 0; +} + +static const Attribute * +find_attribute(const CMSAttributes *attr, const heim_oid *oid) +{ + size_t i; + for (i = 0; i < attr->len; i++) + if (der_heim_oid_cmp(&attr->val[i].type, oid) == 0) + return &attr->val[i]; + return NULL; +} + +/** + * Decode SignedData and verify that the signature is correct. + * + * @param context A hx509 context. + * @param ctx a hx509 verify context. + * @param flags to control the behaivor of the function. + * - HX509_CMS_VS_NO_KU_CHECK - Don't check KeyUsage + * - HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH - allow oid mismatch + * - HX509_CMS_VS_ALLOW_ZERO_SIGNER - no signer, see below. + * @param data pointer to CMS SignedData encoded data. + * @param length length of the data that data point to. + * @param signedContent external data used for signature. + * @param pool certificate pool to build certificates paths. + * @param contentType free with der_free_oid(). + * @param content the output of the function, free with + * der_free_octet_string(). + * @param signer_certs list of the cerficates used to sign this + * request, free with hx509_certs_free(). + * + * @return an hx509 error code. + * + * @ingroup hx509_cms + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cms_verify_signed(hx509_context context, + hx509_verify_ctx ctx, + unsigned int flags, + const void *data, + size_t length, + const heim_octet_string *signedContent, + hx509_certs pool, + heim_oid *contentType, + heim_octet_string *content, + hx509_certs *signer_certs) +{ + unsigned int verify_flags; + + return hx509_cms_verify_signed_ext(context, + ctx, + flags, + data, + length, + signedContent, + pool, + contentType, + content, + signer_certs, + &verify_flags); +} + +/** + * Decode SignedData and verify that the signature is correct. + * + * @param context A hx509 context. + * @param ctx a hx509 verify context. + * @param flags to control the behaivor of the function. + * - HX509_CMS_VS_NO_KU_CHECK - Don't check KeyUsage + * - HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH - allow oid mismatch + * - HX509_CMS_VS_ALLOW_ZERO_SIGNER - no signer, see below. + * @param data pointer to CMS SignedData encoded data. + * @param length length of the data that data point to. + * @param signedContent external data used for signature. + * @param pool certificate pool to build certificates paths. + * @param contentType free with der_free_oid(). + * @param content the output of the function, free with + * der_free_octet_string(). + * @param signer_certs list of the cerficates used to sign this + * request, free with hx509_certs_free(). + * @param verify_flags flags indicating whether the certificate + * was verified or not + * + * @return an hx509 error code. + * + * @ingroup hx509_cms + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cms_verify_signed_ext(hx509_context context, + hx509_verify_ctx ctx, + unsigned int flags, + const void *data, + size_t length, + const heim_octet_string *signedContent, + hx509_certs pool, + heim_oid *contentType, + heim_octet_string *content, + hx509_certs *signer_certs, + unsigned int *verify_flags) +{ + SignerInfo *signer_info; + hx509_cert cert = NULL; + hx509_certs certs = NULL; + SignedData sd; + size_t size; + int ret, found_valid_sig; + size_t i; + + *signer_certs = NULL; + *verify_flags = 0; + + content->data = NULL; + content->length = 0; + contentType->length = 0; + contentType->components = NULL; + + memset(&sd, 0, sizeof(sd)); + + ret = decode_SignedData(data, length, &sd, &size); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to decode SignedData"); + goto out; + } + + if (sd.encapContentInfo.eContent == NULL && signedContent == NULL) { + ret = HX509_CMS_NO_DATA_AVAILABLE; + hx509_set_error_string(context, 0, ret, + "No content data in SignedData"); + goto out; + } + if (sd.encapContentInfo.eContent && signedContent) { + ret = HX509_CMS_NO_DATA_AVAILABLE; + hx509_set_error_string(context, 0, ret, + "Both external and internal SignedData"); + goto out; + } + + if (sd.encapContentInfo.eContent) + ret = der_copy_octet_string(sd.encapContentInfo.eContent, content); + else + ret = der_copy_octet_string(signedContent, content); + if (ret) { + hx509_set_error_string(context, 0, ret, "malloc: out of memory"); + goto out; + } + + ret = hx509_certs_init(context, "MEMORY:cms-cert-buffer", + 0, NULL, &certs); + if (ret) + goto out; + + ret = hx509_certs_init(context, "MEMORY:cms-signer-certs", + 0, NULL, signer_certs); + if (ret) + goto out; + + /* XXX Check CMS version */ + + ret = any_to_certs(context, &sd, certs); + if (ret) + goto out; + + if (pool) { + ret = hx509_certs_merge(context, certs, pool); + if (ret) + goto out; + } + + for (found_valid_sig = 0, i = 0; i < sd.signerInfos.len; i++) { + heim_octet_string signed_data = { 0, 0 }; + const heim_oid *match_oid; + heim_oid decode_oid; + + signer_info = &sd.signerInfos.val[i]; + match_oid = NULL; + + if (signer_info->signature.length == 0) { + ret = HX509_CMS_MISSING_SIGNER_DATA; + hx509_set_error_string(context, 0, ret, + "SignerInfo %d in SignedData " + "missing sigature", i); + continue; + } + + ret = find_CMSIdentifier(context, &signer_info->sid, certs, + _hx509_verify_get_time(ctx), &cert, + HX509_QUERY_KU_DIGITALSIGNATURE); + if (ret) { + /** + * If HX509_CMS_VS_NO_KU_CHECK is set, allow more liberal + * search for matching certificates by not considering + * KeyUsage bits on the certificates. + */ + if ((flags & HX509_CMS_VS_NO_KU_CHECK) == 0) + continue; + + ret = find_CMSIdentifier(context, &signer_info->sid, certs, + _hx509_verify_get_time(ctx), &cert, + 0); + if (ret) + continue; + + } + + if (signer_info->signedAttrs) { + const Attribute *attr; + + CMSAttributes sa; + heim_octet_string os; + + sa.val = signer_info->signedAttrs->val; + sa.len = signer_info->signedAttrs->len; + + /* verify that sigature exists */ + attr = find_attribute(&sa, &asn1_oid_id_pkcs9_messageDigest); + if (attr == NULL) { + ret = HX509_CRYPTO_SIGNATURE_MISSING; + hx509_set_error_string(context, 0, ret, + "SignerInfo have signed attributes " + "but messageDigest (signature) " + "is missing"); + goto next_sigature; + } + if (attr->value.len != 1) { + ret = HX509_CRYPTO_SIGNATURE_MISSING; + hx509_set_error_string(context, 0, ret, + "SignerInfo have more then one " + "messageDigest (signature)"); + goto next_sigature; + } + + ret = decode_MessageDigest(attr->value.val[0].data, + attr->value.val[0].length, + &os, + &size); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to decode " + "messageDigest (signature)"); + goto next_sigature; + } + + ret = _hx509_verify_signature(context, + NULL, + &signer_info->digestAlgorithm, + content, + &os); + der_free_octet_string(&os); + if (ret) { + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + "Failed to verify messageDigest"); + goto next_sigature; + } + + /* + * Fetch content oid inside signedAttrs or set it to + * id-pkcs7-data. + */ + attr = find_attribute(&sa, &asn1_oid_id_pkcs9_contentType); + if (attr == NULL) { + match_oid = &asn1_oid_id_pkcs7_data; + } else { + if (attr->value.len != 1) { + ret = HX509_CMS_DATA_OID_MISMATCH; + hx509_set_error_string(context, 0, ret, + "More then one oid in signedAttrs"); + goto next_sigature; + + } + ret = decode_ContentType(attr->value.val[0].data, + attr->value.val[0].length, + &decode_oid, + &size); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to decode " + "oid in signedAttrs"); + goto next_sigature; + } + match_oid = &decode_oid; + } + + ASN1_MALLOC_ENCODE(CMSAttributes, + signed_data.data, + signed_data.length, + &sa, + &size, ret); + if (ret) { + if (match_oid == &decode_oid) + der_free_oid(&decode_oid); + hx509_clear_error_string(context); + goto next_sigature; + } + if (size != signed_data.length) + _hx509_abort("internal ASN.1 encoder error"); + + } else { + signed_data.data = content->data; + signed_data.length = content->length; + match_oid = &asn1_oid_id_pkcs7_data; + } + + /** + * If HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH, allow + * encapContentInfo mismatch with the oid in signedAttributes + * (or if no signedAttributes where use, pkcs7-data oid). + * This is only needed to work with broken CMS implementations + * that doesn't follow CMS signedAttributes rules. + */ + + if (der_heim_oid_cmp(match_oid, &sd.encapContentInfo.eContentType) && + (flags & HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH) == 0) { + ret = HX509_CMS_DATA_OID_MISMATCH; + hx509_set_error_string(context, 0, ret, + "Oid in message mismatch from the expected"); + } + if (match_oid == &decode_oid) + der_free_oid(&decode_oid); + + if (ret == 0) { + ret = hx509_verify_signature(context, + cert, + &signer_info->signatureAlgorithm, + &signed_data, + &signer_info->signature); + if (ret) + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + "Failed to verify signature in " + "CMS SignedData"); + } + if (signed_data.data != NULL && content->data != signed_data.data) { + free(signed_data.data); + signed_data.data = NULL; + } + if (ret) + goto next_sigature; + + /** + * If HX509_CMS_VS_NO_VALIDATE flags is set, return the signer + * certificate unconditionally but do not set HX509_CMS_VSE_VALIDATED. + */ + ret = hx509_verify_path(context, ctx, cert, certs); + if (ret == 0 || (flags & HX509_CMS_VS_NO_VALIDATE)) { + if (ret == 0) + *verify_flags |= HX509_CMS_VSE_VALIDATED; + + ret = hx509_certs_add(context, *signer_certs, cert); + if (ret == 0) + found_valid_sig++; + } + + next_sigature: + if (cert) + hx509_cert_free(cert); + cert = NULL; + } + /** + * If HX509_CMS_VS_ALLOW_ZERO_SIGNER is set, allow empty + * SignerInfo (no signatures). If SignedData have no signatures, + * the function will return 0 with signer_certs set to NULL. Zero + * signers is allowed by the standard, but since its only useful + * in corner cases, it make into a flag that the caller have to + * turn on. + */ + if (sd.signerInfos.len == 0 && (flags & HX509_CMS_VS_ALLOW_ZERO_SIGNER)) { + if (*signer_certs) + hx509_certs_free(signer_certs); + } else if (found_valid_sig == 0) { + if (ret == 0) { + ret = HX509_CMS_SIGNER_NOT_FOUND; + hx509_set_error_string(context, 0, ret, + "No signers where found"); + } + goto out; + } + + ret = der_copy_oid(&sd.encapContentInfo.eContentType, contentType); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + +out: + free_SignedData(&sd); + if (certs) + hx509_certs_free(&certs); + if (ret) { + if (content->data) + der_free_octet_string(content); + if (*signer_certs) + hx509_certs_free(signer_certs); + der_free_oid(contentType); + der_free_octet_string(content); + } + + return ret; +} + +static int +add_one_attribute(Attribute **attr, + unsigned int *len, + const heim_oid *oid, + heim_octet_string *data) +{ + void *d; + int ret; + + d = realloc(*attr, sizeof((*attr)[0]) * (*len + 1)); + if (d == NULL) + return ENOMEM; + (*attr) = d; + + ret = der_copy_oid(oid, &(*attr)[*len].type); + if (ret) + return ret; + + ALLOC_SEQ(&(*attr)[*len].value, 1); + if ((*attr)[*len].value.val == NULL) { + der_free_oid(&(*attr)[*len].type); + return ENOMEM; + } + + (*attr)[*len].value.val[0].data = data->data; + (*attr)[*len].value.val[0].length = data->length; + + *len += 1; + + return 0; +} + +/** + * Decode SignedData and verify that the signature is correct. + * + * @param context A hx509 context. + * @param flags + * @param eContentType the type of the data. + * @param data data to sign + * @param length length of the data that data point to. + * @param digest_alg digest algorithm to use, use NULL to get the + * default or the peer determined algorithm. + * @param cert certificate to use for sign the data. + * @param peer info about the peer the message to send the message to, + * like what digest algorithm to use. + * @param anchors trust anchors that the client will use, used to + * polulate the certificates included in the message + * @param pool certificates to use in try to build the path to the + * trust anchors. + * @param signed_data the output of the function, free with + * der_free_octet_string(). + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_cms + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cms_create_signed_1(hx509_context context, + int flags, + const heim_oid *eContentType, + const void *data, size_t length, + const AlgorithmIdentifier *digest_alg, + hx509_cert cert, + hx509_peer_info peer, + hx509_certs anchors, + hx509_certs pool, + heim_octet_string *signed_data) +{ + hx509_certs certs; + int ret = 0; + + signed_data->data = NULL; + signed_data->length = 0; + + ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &certs); + if (ret) + return ret; + ret = hx509_certs_add(context, certs, cert); + if (ret) + goto out; + + ret = hx509_cms_create_signed(context, flags, eContentType, data, length, + digest_alg, certs, peer, anchors, pool, + signed_data); + + out: + hx509_certs_free(&certs); + return ret; +} + +struct sigctx { + SignedData sd; + const AlgorithmIdentifier *digest_alg; + const heim_oid *eContentType; + heim_octet_string content; + hx509_peer_info peer; + int cmsidflag; + int leafonly; + hx509_certs certs; + hx509_certs anchors; + hx509_certs pool; +}; + +static int HX509_LIB_CALL +sig_process(hx509_context context, void *ctx, hx509_cert cert) +{ + struct sigctx *sigctx = ctx; + heim_octet_string buf, sigdata = { 0, NULL }; + SignerInfo *signer_info = NULL; + AlgorithmIdentifier digest; + size_t size; + void *ptr; + int ret; + SignedData *sd = &sigctx->sd; + hx509_path path; + + memset(&digest, 0, sizeof(digest)); + memset(&path, 0, sizeof(path)); + + if (_hx509_cert_private_key(cert) == NULL) { + hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING, + "Private key missing for signing"); + return HX509_PRIVATE_KEY_MISSING; + } + + if (sigctx->digest_alg) { + ret = copy_AlgorithmIdentifier(sigctx->digest_alg, &digest); + if (ret) + hx509_clear_error_string(context); + } else { + ret = hx509_crypto_select(context, HX509_SELECT_DIGEST, + _hx509_cert_private_key(cert), + sigctx->peer, &digest); + } + if (ret) + goto out; + + /* + * Allocate on more signerInfo and do the signature processing + */ + + ptr = realloc(sd->signerInfos.val, + (sd->signerInfos.len + 1) * sizeof(sd->signerInfos.val[0])); + if (ptr == NULL) { + ret = ENOMEM; + goto out; + } + sd->signerInfos.val = ptr; + + signer_info = &sd->signerInfos.val[sd->signerInfos.len]; + + memset(signer_info, 0, sizeof(*signer_info)); + + signer_info->version = 1; + + ret = fill_CMSIdentifier(cert, sigctx->cmsidflag, &signer_info->sid); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + + signer_info->signedAttrs = NULL; + signer_info->unsignedAttrs = NULL; + + ret = copy_AlgorithmIdentifier(&digest, &signer_info->digestAlgorithm); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + + /* + * If it isn't pkcs7-data send signedAttributes + */ + + if (der_heim_oid_cmp(sigctx->eContentType, &asn1_oid_id_pkcs7_data) != 0) { + CMSAttributes sa; + heim_octet_string sig; + + ALLOC(signer_info->signedAttrs, 1); + if (signer_info->signedAttrs == NULL) { + ret = ENOMEM; + goto out; + } + + ret = _hx509_create_signature(context, + NULL, + &digest, + &sigctx->content, + NULL, + &sig); + if (ret) + goto out; + + ASN1_MALLOC_ENCODE(MessageDigest, + buf.data, + buf.length, + &sig, + &size, + ret); + der_free_octet_string(&sig); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + if (size != buf.length) + _hx509_abort("internal ASN.1 encoder error"); + + ret = add_one_attribute(&signer_info->signedAttrs->val, + &signer_info->signedAttrs->len, + &asn1_oid_id_pkcs9_messageDigest, + &buf); + if (ret) { + free(buf.data); + hx509_clear_error_string(context); + goto out; + } + + + ASN1_MALLOC_ENCODE(ContentType, + buf.data, + buf.length, + sigctx->eContentType, + &size, + ret); + if (ret) + goto out; + if (size != buf.length) + _hx509_abort("internal ASN.1 encoder error"); + + ret = add_one_attribute(&signer_info->signedAttrs->val, + &signer_info->signedAttrs->len, + &asn1_oid_id_pkcs9_contentType, + &buf); + if (ret) { + free(buf.data); + hx509_clear_error_string(context); + goto out; + } + + sa.val = signer_info->signedAttrs->val; + sa.len = signer_info->signedAttrs->len; + + ASN1_MALLOC_ENCODE(CMSAttributes, + sigdata.data, + sigdata.length, + &sa, + &size, + ret); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + if (size != sigdata.length) + _hx509_abort("internal ASN.1 encoder error"); + } else { + sigdata.data = sigctx->content.data; + sigdata.length = sigctx->content.length; + } + + { + AlgorithmIdentifier sigalg; + + ret = hx509_crypto_select(context, HX509_SELECT_PUBLIC_SIG, + _hx509_cert_private_key(cert), sigctx->peer, + &sigalg); + if (ret) + goto out; + + ret = _hx509_create_signature(context, + _hx509_cert_private_key(cert), + &sigalg, + &sigdata, + &signer_info->signatureAlgorithm, + &signer_info->signature); + free_AlgorithmIdentifier(&sigalg); + if (ret) + goto out; + } + + sigctx->sd.signerInfos.len++; + signer_info = NULL; + + /* + * Provide best effort path + */ + if (sigctx->certs) { + unsigned int i; + + if (sigctx->pool && sigctx->leafonly == 0) { + _hx509_calculate_path(context, + HX509_CALCULATE_PATH_NO_ANCHOR, + time(NULL), + sigctx->anchors, + 0, + cert, + sigctx->pool, + &path); + } else + _hx509_path_append(context, &path, cert); + + for (i = 0; i < path.len; i++) { + /* XXX remove dups */ + ret = hx509_certs_add(context, sigctx->certs, path.val[i]); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + } + } + + out: + if (signer_info) + free_SignerInfo(signer_info); + if (sigdata.data != sigctx->content.data) + der_free_octet_string(&sigdata); + _hx509_path_free(&path); + free_AlgorithmIdentifier(&digest); + + return ret; +} + +static int HX509_LIB_CALL +cert_process(hx509_context context, void *ctx, hx509_cert cert) +{ + struct sigctx *sigctx = ctx; + const unsigned int i = sigctx->sd.certificates->len; + void *ptr; + int ret; + + ptr = realloc(sigctx->sd.certificates->val, + (i + 1) * sizeof(sigctx->sd.certificates->val[0])); + if (ptr == NULL) + return ENOMEM; + sigctx->sd.certificates->val = ptr; + + ret = hx509_cert_binary(context, cert, + &sigctx->sd.certificates->val[i]); + if (ret == 0) + sigctx->sd.certificates->len++; + + return ret; +} + +static int +cmp_AlgorithmIdentifier(const AlgorithmIdentifier *p, const AlgorithmIdentifier *q) +{ + return der_heim_oid_cmp(&p->algorithm, &q->algorithm); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cms_create_signed(hx509_context context, + int flags, + const heim_oid *eContentType, + const void *data, size_t length, + const AlgorithmIdentifier *digest_alg, + hx509_certs certs, + hx509_peer_info peer, + hx509_certs anchors, + hx509_certs pool, + heim_octet_string *signed_data) +{ + unsigned int i, j; + hx509_name name; + int ret; + size_t size; + struct sigctx sigctx; + + memset(&sigctx, 0, sizeof(sigctx)); + memset(&name, 0, sizeof(name)); + + if (eContentType == NULL) + eContentType = &asn1_oid_id_pkcs7_data; + + sigctx.digest_alg = digest_alg; + sigctx.content.data = rk_UNCONST(data); + sigctx.content.length = length; + sigctx.eContentType = eContentType; + sigctx.peer = peer; + /** + * Use HX509_CMS_SIGNATURE_ID_NAME to preferred use of issuer name + * and serial number if possible. Otherwise subject key identifier + * will preferred. + */ + if (flags & HX509_CMS_SIGNATURE_ID_NAME) + sigctx.cmsidflag = CMS_ID_NAME; + else + sigctx.cmsidflag = CMS_ID_SKI; + + /** + * Use HX509_CMS_SIGNATURE_LEAF_ONLY to only request leaf + * certificates to be added to the SignedData. + */ + sigctx.leafonly = (flags & HX509_CMS_SIGNATURE_LEAF_ONLY) ? 1 : 0; + + /** + * Use HX509_CMS_NO_CERTS to make the SignedData contain no + * certificates, overrides HX509_CMS_SIGNATURE_LEAF_ONLY. + */ + + if ((flags & HX509_CMS_SIGNATURE_NO_CERTS) == 0) { + ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &sigctx.certs); + if (ret) + return ret; + } + + sigctx.anchors = anchors; + sigctx.pool = pool; + + sigctx.sd.version = cMSVersion_v3; + + ret = der_copy_oid(eContentType, &sigctx.sd.encapContentInfo.eContentType); + if (ret) + goto out; + + /** + * Use HX509_CMS_SIGNATURE_DETACHED to create detached signatures. + */ + if ((flags & HX509_CMS_SIGNATURE_DETACHED) == 0) { + ALLOC(sigctx.sd.encapContentInfo.eContent, 1); + if (sigctx.sd.encapContentInfo.eContent == NULL) { + hx509_clear_error_string(context); + ret = ENOMEM; + goto out; + } + + sigctx.sd.encapContentInfo.eContent->data = malloc(length); + if (sigctx.sd.encapContentInfo.eContent->data == NULL) { + hx509_clear_error_string(context); + ret = ENOMEM; + goto out; + } + memcpy(sigctx.sd.encapContentInfo.eContent->data, data, length); + sigctx.sd.encapContentInfo.eContent->length = length; + } + + /** + * Use HX509_CMS_SIGNATURE_NO_SIGNER to create no sigInfo (no + * signatures). + */ + if ((flags & HX509_CMS_SIGNATURE_NO_SIGNER) == 0) { + ret = hx509_certs_iter_f(context, certs, sig_process, &sigctx); + if (ret) + goto out; + } + + if (sigctx.sd.signerInfos.len) { + + /* + * For each signerInfo, collect all different digest types. + */ + for (i = 0; i < sigctx.sd.signerInfos.len; i++) { + AlgorithmIdentifier *di = + &sigctx.sd.signerInfos.val[i].digestAlgorithm; + + for (j = 0; j < sigctx.sd.digestAlgorithms.len; j++) + if (cmp_AlgorithmIdentifier(di, &sigctx.sd.digestAlgorithms.val[j]) == 0) + break; + if (j == sigctx.sd.digestAlgorithms.len) { + ret = add_DigestAlgorithmIdentifiers(&sigctx.sd.digestAlgorithms, di); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + } + } + } + + /* + * Add certs we think are needed, build as part of sig_process + */ + if (sigctx.certs) { + ALLOC(sigctx.sd.certificates, 1); + if (sigctx.sd.certificates == NULL) { + hx509_clear_error_string(context); + ret = ENOMEM; + goto out; + } + + ret = hx509_certs_iter_f(context, sigctx.certs, cert_process, &sigctx); + if (ret) + goto out; + } + + ASN1_MALLOC_ENCODE(SignedData, + signed_data->data, signed_data->length, + &sigctx.sd, &size, ret); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + if (signed_data->length != size) + _hx509_abort("internal ASN.1 encoder error"); + +out: + hx509_certs_free(&sigctx.certs); + free_SignedData(&sigctx.sd); + + return ret; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cms_decrypt_encrypted(hx509_context context, + hx509_lock lock, + const void *data, + size_t length, + heim_oid *contentType, + heim_octet_string *content) +{ + heim_octet_string cont; + CMSEncryptedData ed; + AlgorithmIdentifier *ai; + int ret; + + memset(content, 0, sizeof(*content)); + memset(&cont, 0, sizeof(cont)); + + ret = decode_CMSEncryptedData(data, length, &ed, NULL); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to decode CMSEncryptedData"); + return ret; + } + + if (ed.encryptedContentInfo.encryptedContent == NULL) { + ret = HX509_CMS_NO_DATA_AVAILABLE; + hx509_set_error_string(context, 0, ret, + "No content in EncryptedData"); + goto out; + } + + ret = der_copy_oid(&ed.encryptedContentInfo.contentType, contentType); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + + ai = &ed.encryptedContentInfo.contentEncryptionAlgorithm; + if (ai->parameters == NULL) { + ret = HX509_ALG_NOT_SUPP; + hx509_clear_error_string(context); + goto out; + } + + ret = _hx509_pbe_decrypt(context, + lock, + ai, + ed.encryptedContentInfo.encryptedContent, + &cont); + if (ret) + goto out; + + *content = cont; + +out: + if (ret) { + if (cont.data) + free(cont.data); + } + free_CMSEncryptedData(&ed); + return ret; +} diff --git a/third_party/heimdal/lib/hx509/collector.c b/third_party/heimdal/lib/hx509/collector.c new file mode 100644 index 0000000..7b46809 --- /dev/null +++ b/third_party/heimdal/lib/hx509/collector.c @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" + +struct private_key { + AlgorithmIdentifier alg; + hx509_private_key private_key; + heim_octet_string localKeyId; +}; + +struct hx509_collector { + hx509_lock lock; + hx509_certs unenvelop_certs; + hx509_certs certs; + struct { + struct private_key **data; + size_t len; + } val; +}; + + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_collector_alloc(hx509_context context, hx509_lock lock, struct hx509_collector **collector) +{ + struct hx509_collector *c; + int ret; + + *collector = NULL; + + c = calloc(1, sizeof(*c)); + if (c == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + c->lock = lock; + + ret = hx509_certs_init(context, "MEMORY:collector-unenvelop-cert", + 0,NULL, &c->unenvelop_certs); + if (ret) { + free(c); + return ret; + } + c->val.data = NULL; + c->val.len = 0; + ret = hx509_certs_init(context, "MEMORY:collector-tmp-store", + 0, NULL, &c->certs); + if (ret) { + hx509_certs_free(&c->unenvelop_certs); + free(c); + return ret; + } + + *collector = c; + return 0; +} + +HX509_LIB_FUNCTION hx509_lock HX509_LIB_CALL +_hx509_collector_get_lock(struct hx509_collector *c) +{ + return c->lock; +} + + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_collector_certs_add(hx509_context context, + struct hx509_collector *c, + hx509_cert cert) +{ + return hx509_certs_add(context, c->certs, cert); +} + +static void +free_private_key(struct private_key *key) +{ + free_AlgorithmIdentifier(&key->alg); + if (key->private_key) + hx509_private_key_free(&key->private_key); + der_free_octet_string(&key->localKeyId); + free(key); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_collector_private_key_add(hx509_context context, + struct hx509_collector *c, + const AlgorithmIdentifier *alg, + hx509_private_key private_key, + const heim_octet_string *key_data, + const heim_octet_string *localKeyId) +{ + struct private_key *key; + void *d; + int ret; + + key = calloc(1, sizeof(*key)); + if (key == NULL) + return ENOMEM; + + d = realloc(c->val.data, (c->val.len + 1) * sizeof(c->val.data[0])); + if (d == NULL) { + free(key); + hx509_set_error_string(context, 0, ENOMEM, "Out of memory"); + return ENOMEM; + } + c->val.data = d; + + ret = copy_AlgorithmIdentifier(alg, &key->alg); + if (ret) { + hx509_set_error_string(context, 0, ret, "Failed to copy " + "AlgorithmIdentifier"); + goto out; + } + if (private_key) { + key->private_key = private_key; + } else { + ret = hx509_parse_private_key(context, alg, + key_data->data, key_data->length, + HX509_KEY_FORMAT_DER, + &key->private_key); + if (ret) + goto out; + } + if (localKeyId) { + ret = der_copy_octet_string(localKeyId, &key->localKeyId); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to copy localKeyId"); + goto out; + } + } else + memset(&key->localKeyId, 0, sizeof(key->localKeyId)); + + c->val.data[c->val.len] = key; + c->val.len++; + +out: + if (ret) + free_private_key(key); + + return ret; +} + +static int +match_localkeyid(hx509_context context, + struct private_key *value, + hx509_certs certs) +{ + hx509_cert cert; + hx509_query q; + int ret; + + if (value->localKeyId.length == 0) { + hx509_set_error_string(context, 0, HX509_LOCAL_ATTRIBUTE_MISSING, + "No local key attribute on private key"); + return HX509_LOCAL_ATTRIBUTE_MISSING; + } + + _hx509_query_clear(&q); + q.match |= HX509_QUERY_MATCH_LOCAL_KEY_ID; + + q.local_key_id = &value->localKeyId; + + ret = hx509_certs_find(context, certs, &q, &cert); + if (ret == 0 && cert == NULL) + ret = HX509_CERT_NOT_FOUND; + if (ret == 0) { + if (value->private_key) + _hx509_cert_assign_key(cert, value->private_key); + hx509_cert_free(cert); + } + return ret; +} + +static int +match_keys(hx509_context context, struct private_key *value, hx509_certs certs) +{ + hx509_cursor cursor; + hx509_cert c; + int ret, found = HX509_CERT_NOT_FOUND; + + if (value->private_key == NULL) { + hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING, + "No private key to compare with"); + return HX509_PRIVATE_KEY_MISSING; + } + + ret = hx509_certs_start_seq(context, certs, &cursor); + if (ret) + return ret; + + c = NULL; + while (1) { + ret = hx509_certs_next_cert(context, certs, cursor, &c); + if (ret) + break; + if (c == NULL) + break; + if (_hx509_cert_private_key(c)) { + hx509_cert_free(c); + continue; + } + + ret = _hx509_match_keys(c, value->private_key); + if (ret) { + _hx509_cert_assign_key(c, value->private_key); + hx509_cert_free(c); + found = 0; + break; + } + hx509_cert_free(c); + } + + hx509_certs_end_seq(context, certs, cursor); + + if (found) + hx509_clear_error_string(context); + + return found; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_collector_collect_certs(hx509_context context, + struct hx509_collector *c, + hx509_certs *ret_certs) +{ + hx509_certs certs; + int ret; + size_t i; + + *ret_certs = NULL; + + ret = hx509_certs_init(context, "MEMORY:collector-store", 0, NULL, &certs); + if (ret) + return ret; + + ret = hx509_certs_merge(context, certs, c->certs); + if (ret) { + hx509_certs_free(&certs); + return ret; + } + + for (i = 0; i < c->val.len; i++) { + ret = match_localkeyid(context, c->val.data[i], certs); + if (ret == 0) + continue; + ret = match_keys(context, c->val.data[i], certs); + if (ret == 0) + continue; + } + + *ret_certs = certs; + + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_collector_collect_private_keys(hx509_context context, + struct hx509_collector *c, + hx509_private_key **keys) +{ + size_t i, nkeys; + + *keys = NULL; + + for (i = 0, nkeys = 0; i < c->val.len; i++) + if (c->val.data[i]->private_key) + nkeys++; + + *keys = calloc(nkeys + 1, sizeof(**keys)); + if (*keys == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "malloc - out of memory"); + return ENOMEM; + } + + for (i = 0, nkeys = 0; i < c->val.len; i++) { + if (c->val.data[i]->private_key) { + (*keys)[nkeys++] = c->val.data[i]->private_key; + c->val.data[i]->private_key = NULL; + } + } + (*keys)[nkeys] = NULL; + + return 0; +} + + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_collector_free(struct hx509_collector *c) +{ + size_t i; + + if (c->unenvelop_certs) + hx509_certs_free(&c->unenvelop_certs); + if (c->certs) + hx509_certs_free(&c->certs); + for (i = 0; i < c->val.len; i++) + free_private_key(c->val.data[i]); + if (c->val.data) + free(c->val.data); + free(c); +} diff --git a/third_party/heimdal/lib/hx509/crypto-ec.c b/third_party/heimdal/lib/hx509/crypto-ec.c new file mode 100644 index 0000000..46e6cd8 --- /dev/null +++ b/third_party/heimdal/lib/hx509/crypto-ec.c @@ -0,0 +1,533 @@ +/* + * Copyright (c) 2016 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +#ifdef HAVE_HCRYPTO_W_OPENSSL +#include <openssl/ec.h> +#include <openssl/ecdsa.h> +#include <openssl/rsa.h> +#include <openssl/bn.h> +#include <openssl/objects.h> +#define HEIM_NO_CRYPTO_HDRS +#endif /* HAVE_HCRYPTO_W_OPENSSL */ + +#include "hx_locl.h" + +extern const AlgorithmIdentifier _hx509_signature_sha512_data; +extern const AlgorithmIdentifier _hx509_signature_sha384_data; +extern const AlgorithmIdentifier _hx509_signature_sha256_data; +extern const AlgorithmIdentifier _hx509_signature_sha1_data; + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_private_eckey_free(void *eckey) +{ +#ifdef HAVE_HCRYPTO_W_OPENSSL + EC_KEY_free(eckey); +#endif +} + +#ifdef HAVE_HCRYPTO_W_OPENSSL +static int +heim_oid2ecnid(heim_oid *oid) +{ + /* + * Now map to openssl OID fun + */ + + if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP256R1) == 0) + return NID_X9_62_prime256v1; +#ifdef NID_secp521r1 + else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP521R1) == 0) + return NID_secp521r1; +#endif +#ifdef NID_secp384r1 + else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP384R1) == 0) + return NID_secp384r1; +#endif +#ifdef NID_secp160r1 + else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP160R1) == 0) + return NID_secp160r1; +#endif +#ifdef NID_secp160r2 + else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP160R2) == 0) + return NID_secp160r2; +#endif + + return NID_undef; +} + +static int +parse_ECParameters(hx509_context context, + heim_octet_string *parameters, int *nid) +{ + ECParameters ecparam; + size_t size; + int ret; + + if (parameters == NULL) { + ret = HX509_PARSING_KEY_FAILED; + hx509_set_error_string(context, 0, ret, + "EC parameters missing"); + return ret; + } + + ret = decode_ECParameters(parameters->data, parameters->length, + &ecparam, &size); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to decode EC parameters"); + return ret; + } + + if (ecparam.element != choice_ECParameters_namedCurve) { + free_ECParameters(&ecparam); + hx509_set_error_string(context, 0, ret, + "EC parameters is not a named curve"); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + + *nid = heim_oid2ecnid(&ecparam.u.namedCurve); + free_ECParameters(&ecparam); + if (*nid == NID_undef) { + hx509_set_error_string(context, 0, ret, + "Failed to find matcing NID for EC curve"); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + return 0; +} + + +/* + * + */ + +static int +ecdsa_verify_signature(hx509_context context, + const struct signature_alg *sig_alg, + const Certificate *signer, + const AlgorithmIdentifier *alg, + const heim_octet_string *data, + const heim_octet_string *sig) +{ + const AlgorithmIdentifier *digest_alg; + const SubjectPublicKeyInfo *spi; + heim_octet_string digest; + int ret; + EC_KEY *key = NULL; + int groupnid; + EC_GROUP *group; + const unsigned char *p; + long len; + + digest_alg = sig_alg->digest_alg; + + ret = _hx509_create_signature(context, + NULL, + digest_alg, + data, + NULL, + &digest); + if (ret) + return ret; + + /* set up EC KEY */ + spi = &signer->tbsCertificate.subjectPublicKeyInfo; + + if (der_heim_oid_cmp(&spi->algorithm.algorithm, ASN1_OID_ID_ECPUBLICKEY) != 0) + return HX509_CRYPTO_SIG_INVALID_FORMAT; + + /* + * Find the group id + */ + + ret = parse_ECParameters(context, spi->algorithm.parameters, &groupnid); + if (ret) { + der_free_octet_string(&digest); + return ret; + } + + /* + * Create group, key, parse key + */ + + key = EC_KEY_new(); + group = EC_GROUP_new_by_curve_name(groupnid); + EC_KEY_set_group(key, group); + EC_GROUP_free(group); + + p = spi->subjectPublicKey.data; + len = spi->subjectPublicKey.length / 8; + + if (o2i_ECPublicKey(&key, &p, len) == NULL) { + EC_KEY_free(key); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + + ret = ECDSA_verify(-1, digest.data, digest.length, + sig->data, sig->length, key); + der_free_octet_string(&digest); + EC_KEY_free(key); + if (ret != 1) { + ret = HX509_CRYPTO_SIG_INVALID_FORMAT; + return ret; + } + + return 0; +} + +static int +ecdsa_create_signature(hx509_context context, + const struct signature_alg *sig_alg, + const hx509_private_key signer, + const AlgorithmIdentifier *alg, + const heim_octet_string *data, + AlgorithmIdentifier *signatureAlgorithm, + heim_octet_string *sig) +{ + const AlgorithmIdentifier *digest_alg; + heim_octet_string indata; + const heim_oid *sig_oid; + unsigned int siglen; + int ret; + + if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) != 0) + _hx509_abort("internal error passing private key to wrong ops"); + + sig_oid = sig_alg->sig_oid; + digest_alg = sig_alg->digest_alg; + + if (signatureAlgorithm) { + ret = _hx509_set_digest_alg(signatureAlgorithm, sig_oid, + "\x05\x00", 2); + if (ret) { + hx509_clear_error_string(context); + return ret; + } + } + + ret = _hx509_create_signature(context, + NULL, + digest_alg, + data, + NULL, + &indata); + if (ret) + goto error; + + sig->length = ECDSA_size(signer->private_key.ecdsa); + sig->data = malloc(sig->length); + if (sig->data == NULL) { + der_free_octet_string(&indata); + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "out of memory"); + goto error; + } + + siglen = sig->length; + + ret = ECDSA_sign(-1, indata.data, indata.length, + sig->data, &siglen, signer->private_key.ecdsa); + der_free_octet_string(&indata); + if (ret != 1) { + ret = HX509_CMS_FAILED_CREATE_SIGATURE; + hx509_set_error_string(context, 0, ret, + "ECDSA sign failed: %d", ret); + goto error; + } + if (siglen > sig->length) + _hx509_abort("ECDSA signature prelen longer the output len"); + + sig->length = siglen; + + return 0; + error: + if (signatureAlgorithm) + free_AlgorithmIdentifier(signatureAlgorithm); + return ret; +} + +static int +ecdsa_available(const hx509_private_key signer, + const AlgorithmIdentifier *sig_alg) +{ + const struct signature_alg *sig; + const EC_GROUP *group; + BN_CTX *bnctx = NULL; + BIGNUM *order = NULL; + int ret = 0; + + if (der_heim_oid_cmp(signer->ops->key_oid, &asn1_oid_id_ecPublicKey) != 0) + _hx509_abort("internal error passing private key to wrong ops"); + + sig = _hx509_find_sig_alg(&sig_alg->algorithm); + + if (sig == NULL || sig->digest_size == 0) + return 0; + + group = EC_KEY_get0_group(signer->private_key.ecdsa); + if (group == NULL) + return 0; + + bnctx = BN_CTX_new(); + order = BN_new(); + if (order == NULL) + goto err; + + if (EC_GROUP_get_order(group, order, bnctx) != 1) + goto err; + +#if 0 + /* If anything, require a digest at least as wide as the EC key size */ + if (BN_num_bytes(order) > sig->digest_size) +#endif + ret = 1; + err: + if (bnctx) + BN_CTX_free(bnctx); + if (order) + BN_clear_free(order); + + return ret; +} + +static int +ecdsa_private_key2SPKI(hx509_context context, + hx509_private_key private_key, + SubjectPublicKeyInfo *spki) +{ + memset(spki, 0, sizeof(*spki)); + return ENOMEM; +} + +static int +ecdsa_private_key_export(hx509_context context, + const hx509_private_key key, + hx509_key_format_t format, + heim_octet_string *data) +{ + return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; +} + +static int +ecdsa_private_key_import(hx509_context context, + const AlgorithmIdentifier *keyai, + const void *data, + size_t len, + hx509_key_format_t format, + hx509_private_key private_key) +{ + const unsigned char *p = data; + EC_KEY **pkey = NULL; + EC_KEY *key; + + if (keyai->parameters) { + EC_GROUP *group; + int groupnid; + int ret; + + ret = parse_ECParameters(context, keyai->parameters, &groupnid); + if (ret) + return ret; + + key = EC_KEY_new(); + if (key == NULL) + return ENOMEM; + + group = EC_GROUP_new_by_curve_name(groupnid); + if (group == NULL) { + EC_KEY_free(key); + return ENOMEM; + } + EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); + if (EC_KEY_set_group(key, group) == 0) { + EC_KEY_free(key); + EC_GROUP_free(group); + return ENOMEM; + } + EC_GROUP_free(group); + pkey = &key; + } + + switch (format) { + case HX509_KEY_FORMAT_DER: + + private_key->private_key.ecdsa = d2i_ECPrivateKey(pkey, &p, len); + if (private_key->private_key.ecdsa == NULL) { + hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, + "Failed to parse EC private key"); + return HX509_PARSING_KEY_FAILED; + } + private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256; + break; + + default: + return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; + } + + return 0; +} + +static int +ecdsa_generate_private_key(hx509_context context, + struct hx509_generate_private_context *ctx, + hx509_private_key private_key) +{ + return ENOMEM; +} + +static BIGNUM * +ecdsa_get_internal(hx509_context context, + hx509_private_key key, + const char *type) +{ + return NULL; +} + +static const unsigned ecPublicKey[] ={ 1, 2, 840, 10045, 2, 1 }; +const AlgorithmIdentifier _hx509_signature_ecPublicKey = { + { 6, rk_UNCONST(ecPublicKey) }, NULL +}; + +static const unsigned ecdsa_with_sha256_oid[] ={ 1, 2, 840, 10045, 4, 3, 2 }; +const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha256_data = { + { 7, rk_UNCONST(ecdsa_with_sha256_oid) }, NULL +}; + +static const unsigned ecdsa_with_sha384_oid[] ={ 1, 2, 840, 10045, 4, 3, 3 }; +const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha384_data = { + { 7, rk_UNCONST(ecdsa_with_sha384_oid) }, NULL +}; + +static const unsigned ecdsa_with_sha512_oid[] ={ 1, 2, 840, 10045, 4, 3, 4 }; +const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha512_data = { + { 7, rk_UNCONST(ecdsa_with_sha512_oid) }, NULL +}; + +static const unsigned ecdsa_with_sha1_oid[] ={ 1, 2, 840, 10045, 4, 1 }; +const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha1_data = { + { 6, rk_UNCONST(ecdsa_with_sha1_oid) }, NULL +}; + +hx509_private_key_ops ecdsa_private_key_ops = { + "EC PRIVATE KEY", + ASN1_OID_ID_ECPUBLICKEY, + ecdsa_available, + ecdsa_private_key2SPKI, + ecdsa_private_key_export, + ecdsa_private_key_import, + ecdsa_generate_private_key, + ecdsa_get_internal +}; + +const struct signature_alg ecdsa_with_sha512_alg = { + "ecdsa-with-sha512", + ASN1_OID_ID_ECDSA_WITH_SHA512, + &_hx509_signature_ecdsa_with_sha512_data, + ASN1_OID_ID_ECPUBLICKEY, + &_hx509_signature_sha512_data, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO| + SIG_PUBLIC_SIG|SELF_SIGNED_OK, + 0, + NULL, + ecdsa_verify_signature, + ecdsa_create_signature, + 64 +}; + +const struct signature_alg ecdsa_with_sha384_alg = { + "ecdsa-with-sha384", + ASN1_OID_ID_ECDSA_WITH_SHA384, + &_hx509_signature_ecdsa_with_sha384_data, + ASN1_OID_ID_ECPUBLICKEY, + &_hx509_signature_sha384_data, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO| + SIG_PUBLIC_SIG|SELF_SIGNED_OK, + 0, + NULL, + ecdsa_verify_signature, + ecdsa_create_signature, + 48 +}; + +const struct signature_alg ecdsa_with_sha256_alg = { + "ecdsa-with-sha256", + ASN1_OID_ID_ECDSA_WITH_SHA256, + &_hx509_signature_ecdsa_with_sha256_data, + ASN1_OID_ID_ECPUBLICKEY, + &_hx509_signature_sha256_data, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO| + SIG_PUBLIC_SIG|SELF_SIGNED_OK, + 0, + NULL, + ecdsa_verify_signature, + ecdsa_create_signature, + 32 +}; + +const struct signature_alg ecdsa_with_sha1_alg = { + "ecdsa-with-sha1", + ASN1_OID_ID_ECDSA_WITH_SHA1, + &_hx509_signature_ecdsa_with_sha1_data, + ASN1_OID_ID_ECPUBLICKEY, + &_hx509_signature_sha1_data, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO| + SIG_PUBLIC_SIG|SELF_SIGNED_OK, + 0, + NULL, + ecdsa_verify_signature, + ecdsa_create_signature, + 20 +}; + +#endif /* HAVE_HCRYPTO_W_OPENSSL */ + +HX509_LIB_FUNCTION const AlgorithmIdentifier * HX509_LIB_CALL +hx509_signature_ecPublicKey(void) +{ +#ifdef HAVE_HCRYPTO_W_OPENSSL + return &_hx509_signature_ecPublicKey; +#else + return NULL; +#endif /* HAVE_HCRYPTO_W_OPENSSL */ +} + +HX509_LIB_FUNCTION const AlgorithmIdentifier * HX509_LIB_CALL +hx509_signature_ecdsa_with_sha256(void) +{ +#ifdef HAVE_HCRYPTO_W_OPENSSL + return &_hx509_signature_ecdsa_with_sha256_data; +#else + return NULL; +#endif /* HAVE_HCRYPTO_W_OPENSSL */ +} diff --git a/third_party/heimdal/lib/hx509/crypto.c b/third_party/heimdal/lib/hx509/crypto.c new file mode 100644 index 0000000..8d368ed --- /dev/null +++ b/third_party/heimdal/lib/hx509/crypto.c @@ -0,0 +1,2804 @@ +/* + * Copyright (c) 2004 - 2016 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" + +/*- + * RFC5758 specifies no parameters for ecdsa-with-SHA<N> signatures + * RFC5754 specifies NULL parameters for sha<N>WithRSAEncryption signatures + * + * XXX: Make sure that the parameters are either NULL in both the tbs and the + * signature, or absent from both the tbs and the signature. + */ + +static const heim_octet_string null_entry_oid = { 2, rk_UNCONST("\x05\x00") }; + +static const unsigned sha512_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 3 }; +const AlgorithmIdentifier _hx509_signature_sha512_data = { + { 9, rk_UNCONST(sha512_oid_tree) }, rk_UNCONST(&null_entry_oid) +}; + +static const unsigned sha384_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 2 }; +const AlgorithmIdentifier _hx509_signature_sha384_data = { + { 9, rk_UNCONST(sha384_oid_tree) }, rk_UNCONST(&null_entry_oid) +}; + +static const unsigned sha256_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 }; +const AlgorithmIdentifier _hx509_signature_sha256_data = { + { 9, rk_UNCONST(sha256_oid_tree) }, rk_UNCONST(&null_entry_oid) +}; + +static const unsigned sha1_oid_tree[] = { 1, 3, 14, 3, 2, 26 }; +const AlgorithmIdentifier _hx509_signature_sha1_data = { + { 6, rk_UNCONST(sha1_oid_tree) }, rk_UNCONST(&null_entry_oid) +}; + +static const unsigned md5_oid_tree[] = { 1, 2, 840, 113549, 2, 5 }; +const AlgorithmIdentifier _hx509_signature_md5_data = { + { 6, rk_UNCONST(md5_oid_tree) }, rk_UNCONST(&null_entry_oid) +}; + +static const unsigned rsa_with_sha512_oid[] ={ 1, 2, 840, 113549, 1, 1, 13 }; +const AlgorithmIdentifier _hx509_signature_rsa_with_sha512_data = { + { 7, rk_UNCONST(rsa_with_sha512_oid) }, rk_UNCONST(&null_entry_oid) +}; + +static const unsigned rsa_with_sha384_oid[] ={ 1, 2, 840, 113549, 1, 1, 12 }; +const AlgorithmIdentifier _hx509_signature_rsa_with_sha384_data = { + { 7, rk_UNCONST(rsa_with_sha384_oid) }, rk_UNCONST(&null_entry_oid) +}; + +static const unsigned rsa_with_sha256_oid[] ={ 1, 2, 840, 113549, 1, 1, 11 }; +const AlgorithmIdentifier _hx509_signature_rsa_with_sha256_data = { + { 7, rk_UNCONST(rsa_with_sha256_oid) }, rk_UNCONST(&null_entry_oid) +}; + +static const unsigned rsa_with_sha1_oid[] ={ 1, 2, 840, 113549, 1, 1, 5 }; +const AlgorithmIdentifier _hx509_signature_rsa_with_sha1_data = { + { 7, rk_UNCONST(rsa_with_sha1_oid) }, rk_UNCONST(&null_entry_oid) +}; + +static const unsigned rsa_with_md5_oid[] ={ 1, 2, 840, 113549, 1, 1, 4 }; +const AlgorithmIdentifier _hx509_signature_rsa_with_md5_data = { + { 7, rk_UNCONST(rsa_with_md5_oid) }, rk_UNCONST(&null_entry_oid) +}; + +static const unsigned rsa_oid[] ={ 1, 2, 840, 113549, 1, 1, 1 }; +const AlgorithmIdentifier _hx509_signature_rsa_data = { + { 7, rk_UNCONST(rsa_oid) }, NULL +}; + +static const unsigned rsa_pkcs1_x509_oid[] ={ 1, 2, 752, 43, 16, 1 }; +const AlgorithmIdentifier _hx509_signature_rsa_pkcs1_x509_data = { + { 6, rk_UNCONST(rsa_pkcs1_x509_oid) }, NULL +}; + +static const unsigned des_rsdi_ede3_cbc_oid[] ={ 1, 2, 840, 113549, 3, 7 }; +const AlgorithmIdentifier _hx509_des_rsdi_ede3_cbc_oid = { + { 6, rk_UNCONST(des_rsdi_ede3_cbc_oid) }, NULL +}; + +static const unsigned aes128_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 2 }; +const AlgorithmIdentifier _hx509_crypto_aes128_cbc_data = { + { 9, rk_UNCONST(aes128_cbc_oid) }, NULL +}; + +static const unsigned aes256_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 42 }; +const AlgorithmIdentifier _hx509_crypto_aes256_cbc_data = { + { 9, rk_UNCONST(aes256_cbc_oid) }, NULL +}; + +/* + * + */ + +static BIGNUM * +heim_int2BN(const heim_integer *i) +{ + BIGNUM *bn; + + bn = BN_bin2bn(i->data, i->length, NULL); + BN_set_negative(bn, i->negative); + return bn; +} + +/* + * + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_set_digest_alg(DigestAlgorithmIdentifier *id, + const heim_oid *oid, + const void *param, size_t length) +{ + int ret; + if (param) { + id->parameters = malloc(sizeof(*id->parameters)); + if (id->parameters == NULL) + return ENOMEM; + id->parameters->data = malloc(length); + if (id->parameters->data == NULL) { + free(id->parameters); + id->parameters = NULL; + return ENOMEM; + } + memcpy(id->parameters->data, param, length); + id->parameters->length = length; + } else + id->parameters = NULL; + ret = der_copy_oid(oid, &id->algorithm); + if (ret) { + if (id->parameters) { + free(id->parameters->data); + free(id->parameters); + id->parameters = NULL; + } + return ret; + } + return 0; +} + +/* + * + */ + +static int +rsa_verify_signature(hx509_context context, + const struct signature_alg *sig_alg, + const Certificate *signer, + const AlgorithmIdentifier *alg, + const heim_octet_string *data, + const heim_octet_string *sig) +{ + const SubjectPublicKeyInfo *spi; + DigestInfo di; + unsigned char *to; + int tosize, retsize; + int ret; + RSA *rsa; + size_t size; + const unsigned char *p; + + memset(&di, 0, sizeof(di)); + + spi = &signer->tbsCertificate.subjectPublicKeyInfo; + + p = spi->subjectPublicKey.data; + size = spi->subjectPublicKey.length / 8; + + rsa = d2i_RSAPublicKey(NULL, &p, size); + if (rsa == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "out of memory"); + goto out; + } + + tosize = RSA_size(rsa); + to = malloc(tosize); + if (to == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "out of memory"); + goto out; + } + + retsize = RSA_public_decrypt(sig->length, (unsigned char *)sig->data, + to, rsa, RSA_PKCS1_PADDING); + if (retsize <= 0) { + ret = HX509_CRYPTO_SIG_INVALID_FORMAT; + hx509_set_error_string(context, 0, ret, + "RSA public decrypt failed: %d", retsize); + free(to); + goto out; + } + if (retsize > tosize) + _hx509_abort("internal rsa decryption failure: ret > tosize"); + + if (sig_alg->flags & RA_RSA_USES_DIGEST_INFO) { + + ret = decode_DigestInfo(to, retsize, &di, &size); + free(to); + if (ret) { + goto out; + } + + /* Check for extra data inside the sigature */ + if (size != (size_t)retsize) { + ret = HX509_CRYPTO_SIG_INVALID_FORMAT; + hx509_set_error_string(context, 0, ret, "size from decryption mismatch"); + goto out; + } + + if (sig_alg->digest_alg && + der_heim_oid_cmp(&di.digestAlgorithm.algorithm, + &sig_alg->digest_alg->algorithm) != 0) + { + ret = HX509_CRYPTO_OID_MISMATCH; + hx509_set_error_string(context, 0, ret, "object identifier in RSA sig mismatch"); + goto out; + } + + /* verify that the parameters are NULL or the NULL-type */ + if (di.digestAlgorithm.parameters != NULL && + (di.digestAlgorithm.parameters->length != 2 || + memcmp(di.digestAlgorithm.parameters->data, "\x05\x00", 2) != 0)) + { + ret = HX509_CRYPTO_SIG_INVALID_FORMAT; + hx509_set_error_string(context, 0, ret, "Extra parameters inside RSA signature"); + goto out; + } + + ret = _hx509_verify_signature(context, + NULL, + &di.digestAlgorithm, + data, + &di.digest); + if (ret) + goto out; + + } else { + if ((size_t)retsize != data->length || + ct_memcmp(to, data->data, retsize) != 0) + { + ret = HX509_CRYPTO_SIG_INVALID_FORMAT; + hx509_set_error_string(context, 0, ret, "RSA Signature incorrect"); + goto out; + } + free(to); + ret = 0; + } + + out: + free_DigestInfo(&di); + if (rsa) + RSA_free(rsa); + return ret; +} + +static int +rsa_create_signature(hx509_context context, + const struct signature_alg *sig_alg, + const hx509_private_key signer, + const AlgorithmIdentifier *alg, + const heim_octet_string *data, + AlgorithmIdentifier *signatureAlgorithm, + heim_octet_string *sig) +{ + const AlgorithmIdentifier *digest_alg; + heim_octet_string indata; + const heim_oid *sig_oid; + size_t size; + int ret; + + if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) != 0) + return HX509_ALG_NOT_SUPP; + + if (alg) + sig_oid = &alg->algorithm; + else + sig_oid = signer->signature_alg; + + if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA512WITHRSAENCRYPTION) == 0) { + digest_alg = hx509_signature_sha512(); + } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA384WITHRSAENCRYPTION) == 0) { + digest_alg = hx509_signature_sha384(); + } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA256WITHRSAENCRYPTION) == 0) { + digest_alg = hx509_signature_sha256(); + } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION) == 0) { + digest_alg = hx509_signature_sha1(); + } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION) == 0) { + digest_alg = hx509_signature_md5(); + } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION) == 0) { + digest_alg = hx509_signature_md5(); + } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_DSA_WITH_SHA1) == 0) { + digest_alg = hx509_signature_sha1(); + } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0) { + digest_alg = hx509_signature_sha1(); + } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_HEIM_RSA_PKCS1_X509) == 0) { + digest_alg = NULL; + } else + return HX509_ALG_NOT_SUPP; + + if (signatureAlgorithm) { + ret = _hx509_set_digest_alg(signatureAlgorithm, sig_oid, + "\x05\x00", 2); + if (ret) { + hx509_clear_error_string(context); + return ret; + } + } + + if (digest_alg) { + DigestInfo di; + memset(&di, 0, sizeof(di)); + + ret = _hx509_create_signature(context, + NULL, + digest_alg, + data, + &di.digestAlgorithm, + &di.digest); + if (ret) + return ret; + ASN1_MALLOC_ENCODE(DigestInfo, + indata.data, + indata.length, + &di, + &size, + ret); + free_DigestInfo(&di); + if (ret) { + hx509_set_error_string(context, 0, ret, "out of memory"); + return ret; + } + if (indata.length != size) + _hx509_abort("internal ASN.1 encoder error"); + } else { + indata = *data; + } + + sig->length = RSA_size(signer->private_key.rsa); + sig->data = malloc(sig->length); + if (sig->data == NULL) { + der_free_octet_string(&indata); + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + + ret = RSA_private_encrypt(indata.length, indata.data, + sig->data, + signer->private_key.rsa, + RSA_PKCS1_PADDING); + if (indata.data != data->data) + der_free_octet_string(&indata); + if (ret <= 0) { + ret = HX509_CMS_FAILED_CREATE_SIGATURE; + hx509_set_error_string(context, 0, ret, + "RSA private encrypt failed: %d", ret); + return ret; + } + if (sig->length > (size_t)ret) { + size = sig->length - ret; + memmove((uint8_t *)sig->data + size, sig->data, ret); + memset(sig->data, 0, size); + } else if (sig->length < (size_t)ret) + _hx509_abort("RSA signature prelen longer the output len"); + + return 0; +} + +static int +rsa_private_key_import(hx509_context context, + const AlgorithmIdentifier *keyai, + const void *data, + size_t len, + hx509_key_format_t format, + hx509_private_key private_key) +{ + switch (format) { + case HX509_KEY_FORMAT_DER: { + const unsigned char *p = data; + + private_key->private_key.rsa = + d2i_RSAPrivateKey(NULL, &p, len); + if (private_key->private_key.rsa == NULL) { + hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, + "Failed to parse RSA key"); + return HX509_PARSING_KEY_FAILED; + } + private_key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION; + break; + + } + default: + return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; + } + + return 0; +} + +static int +rsa_private_key2SPKI(hx509_context context, + hx509_private_key private_key, + SubjectPublicKeyInfo *spki) +{ + int len, ret; + + memset(spki, 0, sizeof(*spki)); + + len = i2d_RSAPublicKey(private_key->private_key.rsa, NULL); + if (len < 0) + return -1; + + spki->subjectPublicKey.data = malloc(len); + if (spki->subjectPublicKey.data == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "malloc - out of memory"); + return ENOMEM; + } + spki->subjectPublicKey.length = len * 8; + + ret = _hx509_set_digest_alg(&spki->algorithm, + ASN1_OID_ID_PKCS1_RSAENCRYPTION, + "\x05\x00", 2); + if (ret) { + hx509_set_error_string(context, 0, ret, "malloc - out of memory"); + free(spki->subjectPublicKey.data); + spki->subjectPublicKey.data = NULL; + spki->subjectPublicKey.length = 0; + return ret; + } + + { + unsigned char *pp = spki->subjectPublicKey.data; + i2d_RSAPublicKey(private_key->private_key.rsa, &pp); + } + + return 0; +} + +static int +rsa_generate_private_key(hx509_context context, + struct hx509_generate_private_context *ctx, + hx509_private_key private_key) +{ + BIGNUM *e; + int ret; + unsigned long bits; + + static const int default_rsa_e = 65537; + static const int default_rsa_bits = 2048; + + private_key->private_key.rsa = RSA_new(); + if (private_key->private_key.rsa == NULL) { + hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, + "Failed to generate RSA key"); + return HX509_PARSING_KEY_FAILED; + } + + e = BN_new(); + BN_set_word(e, default_rsa_e); + + bits = default_rsa_bits; + + if (ctx->num_bits) + bits = ctx->num_bits; + + ret = RSA_generate_key_ex(private_key->private_key.rsa, bits, e, NULL); + BN_free(e); + if (ret != 1) { + hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, + "Failed to generate RSA key"); + return HX509_PARSING_KEY_FAILED; + } + private_key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION; + + return 0; +} + +static int +rsa_private_key_export(hx509_context context, + const hx509_private_key key, + hx509_key_format_t format, + heim_octet_string *data) +{ + int ret; + + data->data = NULL; + data->length = 0; + + switch (format) { + case HX509_KEY_FORMAT_DER: + + ret = i2d_RSAPrivateKey(key->private_key.rsa, NULL); + if (ret <= 0) { + ret = EINVAL; + hx509_set_error_string(context, 0, ret, + "Private key is not exportable"); + return ret; + } + + data->data = malloc(ret); + if (data->data == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "malloc out of memory"); + return ret; + } + data->length = ret; + + { + unsigned char *p = data->data; + i2d_RSAPrivateKey(key->private_key.rsa, &p); + } + break; + default: + return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; + } + + return 0; +} + +static BIGNUM * +rsa_get_internal(hx509_context context, + hx509_private_key key, + const char *type) +{ + if (strcasecmp(type, "rsa-modulus") == 0) { + return BN_dup(key->private_key.rsa->n); + } else if (strcasecmp(type, "rsa-exponent") == 0) { + return BN_dup(key->private_key.rsa->e); + } else + return NULL; +} + + + +static hx509_private_key_ops rsa_private_key_ops = { + "RSA PRIVATE KEY", + ASN1_OID_ID_PKCS1_RSAENCRYPTION, + NULL, + rsa_private_key2SPKI, + rsa_private_key_export, + rsa_private_key_import, + rsa_generate_private_key, + rsa_get_internal +}; + +/* + * + */ + +static int +dsa_verify_signature(hx509_context context, + const struct signature_alg *sig_alg, + const Certificate *signer, + const AlgorithmIdentifier *alg, + const heim_octet_string *data, + const heim_octet_string *sig) +{ + const SubjectPublicKeyInfo *spi; + DSAPublicKey pk; + DSAParams param; + size_t size; + DSA *dsa; + int ret; + + spi = &signer->tbsCertificate.subjectPublicKeyInfo; + + dsa = DSA_new(); + if (dsa == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + + ret = decode_DSAPublicKey(spi->subjectPublicKey.data, + spi->subjectPublicKey.length / 8, + &pk, &size); + if (ret) + goto out; + + dsa->pub_key = heim_int2BN(&pk); + + free_DSAPublicKey(&pk); + + if (dsa->pub_key == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "out of memory"); + goto out; + } + + if (spi->algorithm.parameters == NULL) { + ret = HX509_CRYPTO_SIG_INVALID_FORMAT; + hx509_set_error_string(context, 0, ret, "DSA parameters missing"); + goto out; + } + + ret = decode_DSAParams(spi->algorithm.parameters->data, + spi->algorithm.parameters->length, + ¶m, + &size); + if (ret) { + hx509_set_error_string(context, 0, ret, "DSA parameters failed to decode"); + goto out; + } + + dsa->p = heim_int2BN(¶m.p); + dsa->q = heim_int2BN(¶m.q); + dsa->g = heim_int2BN(¶m.g); + + free_DSAParams(¶m); + + if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "out of memory"); + goto out; + } + + ret = DSA_verify(-1, data->data, data->length, + (unsigned char*)sig->data, sig->length, + dsa); + if (ret == 1) + ret = 0; + else if (ret == 0 || ret == -1) { + ret = HX509_CRYPTO_BAD_SIGNATURE; + hx509_set_error_string(context, 0, ret, "BAD DSA sigature"); + } else { + ret = HX509_CRYPTO_SIG_INVALID_FORMAT; + hx509_set_error_string(context, 0, ret, "Invalid format of DSA sigature"); + } + + out: + DSA_free(dsa); + + return ret; +} + +#if 0 +static int +dsa_parse_private_key(hx509_context context, + const void *data, + size_t len, + hx509_private_key private_key) +{ + const unsigned char *p = data; + + private_key->private_key.dsa = + d2i_DSAPrivateKey(NULL, &p, len); + if (private_key->private_key.dsa == NULL) + return EINVAL; + private_key->signature_alg = ASN1_OID_ID_DSA_WITH_SHA1; + + return 0; +/* else */ + hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, + "No support to parse DSA keys"); + return HX509_PARSING_KEY_FAILED; +} +#endif + +static int +evp_md_create_signature(hx509_context context, + const struct signature_alg *sig_alg, + const hx509_private_key signer, + const AlgorithmIdentifier *alg, + const heim_octet_string *data, + AlgorithmIdentifier *signatureAlgorithm, + heim_octet_string *sig) +{ + size_t sigsize = EVP_MD_size(sig_alg->evp_md()); + EVP_MD_CTX *ctx; + + memset(sig, 0, sizeof(*sig)); + + if (signatureAlgorithm) { + int ret; + ret = _hx509_set_digest_alg(signatureAlgorithm, + sig_alg->sig_oid, "\x05\x00", 2); + if (ret) + return ret; + } + + + sig->data = malloc(sigsize); + if (sig->data == NULL) { + sig->length = 0; + return ENOMEM; + } + sig->length = sigsize; + + ctx = EVP_MD_CTX_create(); + EVP_DigestInit_ex(ctx, sig_alg->evp_md(), NULL); + EVP_DigestUpdate(ctx, data->data, data->length); + EVP_DigestFinal_ex(ctx, sig->data, NULL); + EVP_MD_CTX_destroy(ctx); + + + return 0; +} + +static int +evp_md_verify_signature(hx509_context context, + const struct signature_alg *sig_alg, + const Certificate *signer, + const AlgorithmIdentifier *alg, + const heim_octet_string *data, + const heim_octet_string *sig) +{ + unsigned char digest[EVP_MAX_MD_SIZE]; + EVP_MD_CTX *ctx; + size_t sigsize = EVP_MD_size(sig_alg->evp_md()); + + if (sig->length != sigsize || sigsize > sizeof(digest)) { + hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, + "SHA256 sigature have wrong length"); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + + ctx = EVP_MD_CTX_create(); + EVP_DigestInit_ex(ctx, sig_alg->evp_md(), NULL); + EVP_DigestUpdate(ctx, data->data, data->length); + EVP_DigestFinal_ex(ctx, digest, NULL); + EVP_MD_CTX_destroy(ctx); + + if (ct_memcmp(digest, sig->data, sigsize) != 0) { + hx509_set_error_string(context, 0, HX509_CRYPTO_BAD_SIGNATURE, + "Bad %s sigature", sig_alg->name); + return HX509_CRYPTO_BAD_SIGNATURE; + } + + return 0; +} + +#ifdef HAVE_HCRYPTO_W_OPENSSL +extern const struct signature_alg ecdsa_with_sha512_alg; +extern const struct signature_alg ecdsa_with_sha384_alg; +extern const struct signature_alg ecdsa_with_sha256_alg; +extern const struct signature_alg ecdsa_with_sha1_alg; +#endif + +static const struct signature_alg heim_rsa_pkcs1_x509 = { + "rsa-pkcs1-x509", + ASN1_OID_ID_HEIM_RSA_PKCS1_X509, + &_hx509_signature_rsa_pkcs1_x509_data, + ASN1_OID_ID_PKCS1_RSAENCRYPTION, + NULL, + PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG, + 0, + NULL, + rsa_verify_signature, + rsa_create_signature, + 0 +}; + +static const struct signature_alg pkcs1_rsa_sha1_alg = { + "rsa", + ASN1_OID_ID_PKCS1_RSAENCRYPTION, + &_hx509_signature_rsa_with_sha1_data, + ASN1_OID_ID_PKCS1_RSAENCRYPTION, + NULL, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK, + 0, + NULL, + rsa_verify_signature, + rsa_create_signature, + 0 +}; + +static const struct signature_alg rsa_with_sha512_alg = { + "rsa-with-sha512", + ASN1_OID_ID_PKCS1_SHA512WITHRSAENCRYPTION, + &_hx509_signature_rsa_with_sha512_data, + ASN1_OID_ID_PKCS1_RSAENCRYPTION, + &_hx509_signature_sha512_data, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK, + 0, + NULL, + rsa_verify_signature, + rsa_create_signature, + 0 +}; + +static const struct signature_alg rsa_with_sha384_alg = { + "rsa-with-sha384", + ASN1_OID_ID_PKCS1_SHA384WITHRSAENCRYPTION, + &_hx509_signature_rsa_with_sha384_data, + ASN1_OID_ID_PKCS1_RSAENCRYPTION, + &_hx509_signature_sha384_data, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK, + 0, + NULL, + rsa_verify_signature, + rsa_create_signature, + 0 +}; + +static const struct signature_alg rsa_with_sha256_alg = { + "rsa-with-sha256", + ASN1_OID_ID_PKCS1_SHA256WITHRSAENCRYPTION, + &_hx509_signature_rsa_with_sha256_data, + ASN1_OID_ID_PKCS1_RSAENCRYPTION, + &_hx509_signature_sha256_data, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK, + 0, + NULL, + rsa_verify_signature, + rsa_create_signature, + 0 +}; + +static const struct signature_alg rsa_with_sha1_alg = { + "rsa-with-sha1", + ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION, + &_hx509_signature_rsa_with_sha1_data, + ASN1_OID_ID_PKCS1_RSAENCRYPTION, + &_hx509_signature_sha1_data, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK, + 0, + NULL, + rsa_verify_signature, + rsa_create_signature, + 0 +}; + +static const struct signature_alg rsa_with_sha1_alg_secsig = { + "rsa-with-sha1", + ASN1_OID_ID_SECSIG_SHA_1WITHRSAENCRYPTION, + &_hx509_signature_rsa_with_sha1_data, + ASN1_OID_ID_PKCS1_RSAENCRYPTION, + &_hx509_signature_sha1_data, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK, + 0, + NULL, + rsa_verify_signature, + rsa_create_signature, + 0 +}; + +static const struct signature_alg rsa_with_md5_alg = { + "rsa-with-md5", + ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION, + &_hx509_signature_rsa_with_md5_data, + ASN1_OID_ID_PKCS1_RSAENCRYPTION, + &_hx509_signature_md5_data, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|WEAK_SIG_ALG, + 1230739889, + NULL, + rsa_verify_signature, + rsa_create_signature, + 0 +}; + +static const struct signature_alg dsa_sha1_alg = { + "dsa-with-sha1", + ASN1_OID_ID_DSA_WITH_SHA1, + NULL, + ASN1_OID_ID_DSA, + &_hx509_signature_sha1_data, + PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG, + 0, + NULL, + dsa_verify_signature, + /* create_signature */ NULL, + 0 +}; + +static const struct signature_alg sha512_alg = { + "sha-512", + ASN1_OID_ID_SHA512, + &_hx509_signature_sha512_data, + NULL, + NULL, + SIG_DIGEST, + 0, + EVP_sha512, + evp_md_verify_signature, + evp_md_create_signature, + 0 +}; + +static const struct signature_alg sha384_alg = { + "sha-384", + ASN1_OID_ID_SHA384, + &_hx509_signature_sha384_data, + NULL, + NULL, + SIG_DIGEST, + 0, + EVP_sha384, + evp_md_verify_signature, + evp_md_create_signature, + 0 +}; + +static const struct signature_alg sha256_alg = { + "sha-256", + ASN1_OID_ID_SHA256, + &_hx509_signature_sha256_data, + NULL, + NULL, + SIG_DIGEST, + 0, + EVP_sha256, + evp_md_verify_signature, + evp_md_create_signature, + 0 +}; + +static const struct signature_alg sha1_alg = { + "sha1", + ASN1_OID_ID_SECSIG_SHA_1, + &_hx509_signature_sha1_data, + NULL, + NULL, + SIG_DIGEST, + 0, + EVP_sha1, + evp_md_verify_signature, + evp_md_create_signature, + 0 +}; + +static const struct signature_alg md5_alg = { + "rsa-md5", + ASN1_OID_ID_RSA_DIGEST_MD5, + &_hx509_signature_md5_data, + NULL, + NULL, + SIG_DIGEST|WEAK_SIG_ALG, + 0, + EVP_md5, + evp_md_verify_signature, + NULL, + 0 +}; + +/* + * Order matter in this structure, "best" first for each "key + * compatible" type (type is ECDSA, RSA, DSA, none, etc) + */ + +static const struct signature_alg *sig_algs[] = { +#ifdef HAVE_HCRYPTO_W_OPENSSL + &ecdsa_with_sha512_alg, + &ecdsa_with_sha384_alg, + &ecdsa_with_sha256_alg, + &ecdsa_with_sha1_alg, +#endif + &rsa_with_sha512_alg, + &rsa_with_sha384_alg, + &rsa_with_sha256_alg, + &rsa_with_sha1_alg, + &rsa_with_sha1_alg_secsig, + &pkcs1_rsa_sha1_alg, + &rsa_with_md5_alg, + &heim_rsa_pkcs1_x509, + &dsa_sha1_alg, + &sha512_alg, + &sha384_alg, + &sha256_alg, + &sha1_alg, + &md5_alg, + NULL +}; + +const struct signature_alg * +_hx509_find_sig_alg(const heim_oid *oid) +{ + unsigned int i; + for (i = 0; sig_algs[i]; i++) + if (der_heim_oid_cmp(sig_algs[i]->sig_oid, oid) == 0) + return sig_algs[i]; + return NULL; +} + +static const AlgorithmIdentifier * +alg_for_privatekey(const hx509_private_key pk, int type) +{ + const heim_oid *keytype; + unsigned int i; + + if (pk->ops == NULL) + return NULL; + + keytype = pk->ops->key_oid; + + for (i = 0; sig_algs[i]; i++) { + if (sig_algs[i]->key_oid == NULL) + continue; + if (der_heim_oid_cmp(sig_algs[i]->key_oid, keytype) != 0) + continue; + if (pk->ops->available && + pk->ops->available(pk, sig_algs[i]->sig_alg) == 0) + continue; + if (type == HX509_SELECT_PUBLIC_SIG) + return sig_algs[i]->sig_alg; + if (type == HX509_SELECT_DIGEST) + return sig_algs[i]->digest_alg; + + return NULL; + } + return NULL; +} + +/* + * + */ +#ifdef HAVE_HCRYPTO_W_OPENSSL +extern hx509_private_key_ops ecdsa_private_key_ops; +#endif + +static struct hx509_private_key_ops *private_algs[] = { + &rsa_private_key_ops, +#ifdef HAVE_HCRYPTO_W_OPENSSL + &ecdsa_private_key_ops, +#endif + NULL +}; + +HX509_LIB_FUNCTION hx509_private_key_ops * HX509_LIB_CALL +hx509_find_private_alg(const heim_oid *oid) +{ + int i; + for (i = 0; private_algs[i]; i++) { + if (private_algs[i]->key_oid == NULL) + continue; + if (der_heim_oid_cmp(private_algs[i]->key_oid, oid) == 0) + return private_algs[i]; + } + return NULL; +} + +/* + * Check if the algorithm `alg' have a best before date, and if it + * des, make sure the its before the time `t'. + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_signature_is_weak(hx509_context context, const AlgorithmIdentifier *alg) +{ + const struct signature_alg *md; + + md = _hx509_find_sig_alg(&alg->algorithm); + if (md == NULL) { + hx509_clear_error_string(context); + return HX509_SIG_ALG_NO_SUPPORTED; + } + if (md->flags & WEAK_SIG_ALG) { + hx509_set_error_string(context, 0, HX509_CRYPTO_ALGORITHM_BEST_BEFORE, + "Algorithm %s is weak", md->name); + return HX509_CRYPTO_ALGORITHM_BEST_BEFORE; + } + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_self_signed_valid(hx509_context context, + const AlgorithmIdentifier *alg) +{ + const struct signature_alg *md; + + md = _hx509_find_sig_alg(&alg->algorithm); + if (md == NULL) { + hx509_clear_error_string(context); + return HX509_SIG_ALG_NO_SUPPORTED; + } + if ((md->flags & SELF_SIGNED_OK) == 0) { + hx509_set_error_string(context, 0, HX509_CRYPTO_ALGORITHM_BEST_BEFORE, + "Algorithm %s not trusted for self signatures", + md->name); + return HX509_CRYPTO_ALGORITHM_BEST_BEFORE; + } + return 0; +} + + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_verify_signature(hx509_context context, + const hx509_cert cert, + const AlgorithmIdentifier *alg, + const heim_octet_string *data, + const heim_octet_string *sig) +{ + const struct signature_alg *md; + const Certificate *signer = NULL; + + if (cert) + signer = _hx509_get_cert(cert); + + md = _hx509_find_sig_alg(&alg->algorithm); + if (md == NULL) { + hx509_clear_error_string(context); + return HX509_SIG_ALG_NO_SUPPORTED; + } + if (signer && (md->flags & PROVIDE_CONF) == 0) { + hx509_clear_error_string(context); + return HX509_CRYPTO_SIG_NO_CONF; + } + if (signer == NULL && (md->flags & REQUIRE_SIGNER)) { + hx509_clear_error_string(context); + return HX509_CRYPTO_SIGNATURE_WITHOUT_SIGNER; + } + if (md->key_oid && signer) { + const SubjectPublicKeyInfo *spi; + spi = &signer->tbsCertificate.subjectPublicKeyInfo; + + if (der_heim_oid_cmp(&spi->algorithm.algorithm, md->key_oid) != 0) { + hx509_clear_error_string(context); + return HX509_SIG_ALG_DONT_MATCH_KEY_ALG; + } + } + return (*md->verify_signature)(context, md, signer, alg, data, sig); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_create_signature(hx509_context context, + const hx509_private_key signer, + const AlgorithmIdentifier *alg, + const heim_octet_string *data, + AlgorithmIdentifier *signatureAlgorithm, + heim_octet_string *sig) +{ + const struct signature_alg *md; + + md = _hx509_find_sig_alg(&alg->algorithm); + if (md == NULL) { + hx509_set_error_string(context, 0, HX509_SIG_ALG_NO_SUPPORTED, + "algorithm no supported"); + return HX509_SIG_ALG_NO_SUPPORTED; + } + + if (signer && (md->flags & PROVIDE_CONF) == 0) { + hx509_set_error_string(context, 0, HX509_SIG_ALG_NO_SUPPORTED, + "algorithm provides no conf"); + return HX509_CRYPTO_SIG_NO_CONF; + } + + return (*md->create_signature)(context, md, signer, alg, data, + signatureAlgorithm, sig); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_create_signature_bitstring(hx509_context context, + const hx509_private_key signer, + const AlgorithmIdentifier *alg, + const heim_octet_string *data, + AlgorithmIdentifier *signatureAlgorithm, + heim_bit_string *sig) +{ + heim_octet_string os; + int ret; + + ret = _hx509_create_signature(context, signer, alg, + data, signatureAlgorithm, &os); + if (ret) + return ret; + sig->data = os.data; + sig->length = os.length * 8; + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_public_encrypt(hx509_context context, + const heim_octet_string *cleartext, + const Certificate *cert, + heim_oid *encryption_oid, + heim_octet_string *ciphertext) +{ + const SubjectPublicKeyInfo *spi; + unsigned char *to; + int tosize; + int ret; + RSA *rsa; + size_t size; + const unsigned char *p; + + ciphertext->data = NULL; + ciphertext->length = 0; + + spi = &cert->tbsCertificate.subjectPublicKeyInfo; + + p = spi->subjectPublicKey.data; + size = spi->subjectPublicKey.length / 8; + + rsa = d2i_RSAPublicKey(NULL, &p, size); + if (rsa == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + + tosize = RSA_size(rsa); + to = malloc(tosize); + if (to == NULL) { + RSA_free(rsa); + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + + ret = RSA_public_encrypt(cleartext->length, + (unsigned char *)cleartext->data, + to, rsa, RSA_PKCS1_PADDING); + RSA_free(rsa); + if (ret <= 0) { + free(to); + hx509_set_error_string(context, 0, HX509_CRYPTO_RSA_PUBLIC_ENCRYPT, + "RSA public encrypt failed with %d", ret); + return HX509_CRYPTO_RSA_PUBLIC_ENCRYPT; + } + if (ret > tosize) + _hx509_abort("internal rsa decryption failure: ret > tosize"); + + ciphertext->length = ret; + ciphertext->data = to; + + ret = der_copy_oid(ASN1_OID_ID_PKCS1_RSAENCRYPTION, encryption_oid); + if (ret) { + der_free_octet_string(ciphertext); + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_private_key_private_decrypt(hx509_context context, + const heim_octet_string *ciphertext, + const heim_oid *encryption_oid, + hx509_private_key p, + heim_octet_string *cleartext) +{ + int ret; + + cleartext->data = NULL; + cleartext->length = 0; + + if (p->private_key.rsa == NULL) { + hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING, + "Private RSA key missing"); + return HX509_PRIVATE_KEY_MISSING; + } + + cleartext->length = RSA_size(p->private_key.rsa); + cleartext->data = malloc(cleartext->length); + if (cleartext->data == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + ret = RSA_private_decrypt(ciphertext->length, ciphertext->data, + cleartext->data, + p->private_key.rsa, + RSA_PKCS1_PADDING); + if (ret <= 0) { + der_free_octet_string(cleartext); + hx509_set_error_string(context, 0, HX509_CRYPTO_RSA_PRIVATE_DECRYPT, + "Failed to decrypt using private key: %d", ret); + return HX509_CRYPTO_RSA_PRIVATE_DECRYPT; + } + if (cleartext->length < (size_t)ret) + _hx509_abort("internal rsa decryption failure: ret > tosize"); + + cleartext->length = ret; + + return 0; +} + + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_parse_private_key(hx509_context context, + const AlgorithmIdentifier *keyai, + const void *data, + size_t len, + hx509_key_format_t format, + hx509_private_key *private_key) +{ + struct hx509_private_key_ops *ops; + int ret; + + *private_key = NULL; + + if (format == HX509_KEY_FORMAT_PKCS8) { + PKCS8PrivateKeyInfo ki; + hx509_private_key key; + + ret = decode_PKCS8PrivateKeyInfo(data, len, &ki, NULL); + if (ret) { + hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, + "Failed to parse PKCS#8-encoded private " + "key"); + return HX509_PARSING_KEY_FAILED; + } + + /* Re-enter to parse DER-encoded key from PKCS#8 envelope */ + ret = hx509_parse_private_key(context, &ki.privateKeyAlgorithm, + ki.privateKey.data, ki.privateKey.length, + HX509_KEY_FORMAT_DER, &key); + free_PKCS8PrivateKeyInfo(&ki); + if (ret) { + hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, + "Failed to parse RSA key from PKCS#8 " + "envelope"); + return HX509_PARSING_KEY_FAILED; + } + + *private_key = key; + return ret; + } + + ops = hx509_find_private_alg(&keyai->algorithm); + if (ops == NULL) { + hx509_clear_error_string(context); + return HX509_SIG_ALG_NO_SUPPORTED; + } + + ret = hx509_private_key_init(private_key, ops, NULL); + if (ret) { + hx509_set_error_string(context, 0, ret, "out of memory"); + return ret; + } + + ret = (*ops->import)(context, keyai, data, len, format, *private_key); + if (ret) + hx509_private_key_free(private_key); + + return ret; +} + +/* + * + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_private_key2SPKI(hx509_context context, + hx509_private_key private_key, + SubjectPublicKeyInfo *spki) +{ + const struct hx509_private_key_ops *ops = private_key->ops; + if (ops == NULL || ops->get_spki == NULL) { + hx509_set_error_string(context, 0, HX509_UNIMPLEMENTED_OPERATION, + "Private key have no key2SPKI function"); + return HX509_UNIMPLEMENTED_OPERATION; + } + return (*ops->get_spki)(context, private_key, spki); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_generate_private_key_init(hx509_context context, + const heim_oid *oid, + struct hx509_generate_private_context **ctx) +{ + *ctx = NULL; + + if (der_heim_oid_cmp(oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) != 0) { + hx509_set_error_string(context, 0, EINVAL, + "private key not an RSA key"); + return EINVAL; + } + + *ctx = calloc(1, sizeof(**ctx)); + if (*ctx == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + (*ctx)->key_oid = oid; + + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_generate_private_key_is_ca(hx509_context context, + struct hx509_generate_private_context *ctx) +{ + ctx->isCA = 1; + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_generate_private_key_bits(hx509_context context, + struct hx509_generate_private_context *ctx, + unsigned long bits) +{ + ctx->num_bits = bits; + return 0; +} + + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_generate_private_key_free(struct hx509_generate_private_context **ctx) +{ + free(*ctx); + *ctx = NULL; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_generate_private_key(hx509_context context, + struct hx509_generate_private_context *ctx, + hx509_private_key *private_key) +{ + struct hx509_private_key_ops *ops; + int ret; + + *private_key = NULL; + + ops = hx509_find_private_alg(ctx->key_oid); + if (ops == NULL) { + hx509_clear_error_string(context); + return HX509_SIG_ALG_NO_SUPPORTED; + } + + ret = hx509_private_key_init(private_key, ops, NULL); + if (ret) { + hx509_set_error_string(context, 0, ret, "out of memory"); + return ret; + } + + ret = (*ops->generate_private_key)(context, ctx, *private_key); + if (ret) + hx509_private_key_free(private_key); + + return ret; +} + +/* + * + */ + +const AlgorithmIdentifier * +hx509_signature_sha512(void) +{ return &_hx509_signature_sha512_data; } + +const AlgorithmIdentifier * +hx509_signature_sha384(void) +{ return &_hx509_signature_sha384_data; } + +const AlgorithmIdentifier * +hx509_signature_sha256(void) +{ return &_hx509_signature_sha256_data; } + +const AlgorithmIdentifier * +hx509_signature_sha1(void) +{ return &_hx509_signature_sha1_data; } + +const AlgorithmIdentifier * +hx509_signature_md5(void) +{ return &_hx509_signature_md5_data; } + +const AlgorithmIdentifier * +hx509_signature_rsa_with_sha512(void) +{ return &_hx509_signature_rsa_with_sha512_data; } + +const AlgorithmIdentifier * +hx509_signature_rsa_with_sha384(void) +{ return &_hx509_signature_rsa_with_sha384_data; } + +const AlgorithmIdentifier * +hx509_signature_rsa_with_sha256(void) +{ return &_hx509_signature_rsa_with_sha256_data; } + +const AlgorithmIdentifier * +hx509_signature_rsa_with_sha1(void) +{ return &_hx509_signature_rsa_with_sha1_data; } + +const AlgorithmIdentifier * +hx509_signature_rsa_with_md5(void) +{ return &_hx509_signature_rsa_with_md5_data; } + +const AlgorithmIdentifier * +hx509_signature_rsa(void) +{ return &_hx509_signature_rsa_data; } + +const AlgorithmIdentifier * +hx509_signature_rsa_pkcs1_x509(void) +{ return &_hx509_signature_rsa_pkcs1_x509_data; } + +const AlgorithmIdentifier * +hx509_crypto_des_rsdi_ede3_cbc(void) +{ return &_hx509_des_rsdi_ede3_cbc_oid; } + +const AlgorithmIdentifier * +hx509_crypto_aes128_cbc(void) +{ return &_hx509_crypto_aes128_cbc_data; } + +const AlgorithmIdentifier * +hx509_crypto_aes256_cbc(void) +{ return &_hx509_crypto_aes256_cbc_data; } + +/* + * + */ + +const AlgorithmIdentifier * _hx509_crypto_default_sig_alg = + &_hx509_signature_rsa_with_sha256_data; +const AlgorithmIdentifier * _hx509_crypto_default_digest_alg = + &_hx509_signature_sha256_data; +const AlgorithmIdentifier * _hx509_crypto_default_secret_alg = + &_hx509_crypto_aes128_cbc_data; + +/* + * + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_private_key_init(hx509_private_key *key, + hx509_private_key_ops *ops, + void *keydata) +{ + *key = calloc(1, sizeof(**key)); + if (*key == NULL) + return ENOMEM; + (*key)->ref = 1; + (*key)->ops = ops; + (*key)->private_key.keydata = keydata; + return 0; +} + +HX509_LIB_FUNCTION hx509_private_key HX509_LIB_CALL +_hx509_private_key_ref(hx509_private_key key) +{ + if (key->ref == 0) + _hx509_abort("key refcount <= 0 on ref"); + key->ref++; + if (key->ref == UINT_MAX) + _hx509_abort("key refcount == UINT_MAX on ref"); + return key; +} + +HX509_LIB_FUNCTION const char * HX509_LIB_CALL +_hx509_private_pem_name(hx509_private_key key) +{ + return key->ops->pemtype; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_private_key_free(hx509_private_key *key) +{ + if (key == NULL || *key == NULL) + return 0; + + if ((*key)->ref == 0) + _hx509_abort("key refcount == 0 on free"); + if (--(*key)->ref > 0) + return 0; + + if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0) { + if ((*key)->private_key.rsa) + RSA_free((*key)->private_key.rsa); + } else if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, + ASN1_OID_ID_ECPUBLICKEY) == 0 && + (*key)->private_key.ecdsa != NULL) { + _hx509_private_eckey_free((*key)->private_key.ecdsa); + } + (*key)->private_key.rsa = NULL; + free(*key); + *key = NULL; + return 0; +} + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_private_key_assign_rsa(hx509_private_key key, void *ptr) +{ + if (key->private_key.rsa) + RSA_free(key->private_key.rsa); + key->private_key.rsa = ptr; + key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION; + key->md = &pkcs1_rsa_sha1_alg; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_private_key_oid(hx509_context context, + const hx509_private_key key, + heim_oid *data) +{ + int ret; + ret = der_copy_oid(key->ops->key_oid, data); + if (ret) + hx509_set_error_string(context, 0, ret, "malloc out of memory"); + return ret; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_private_key_exportable(hx509_private_key key) +{ + if (key->ops->export == NULL) + return 0; + return 1; +} + +HX509_LIB_FUNCTION BIGNUM * HX509_LIB_CALL +_hx509_private_key_get_internal(hx509_context context, + hx509_private_key key, + const char *type) +{ + if (key->ops->get_internal == NULL) + return NULL; + return (*key->ops->get_internal)(context, key, type); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_private_key_export(hx509_context context, + const hx509_private_key key, + hx509_key_format_t format, + heim_octet_string *data) +{ + data->length = 0; + data->data = NULL; + if (key->ops->export == NULL) { + hx509_clear_error_string(context); + return HX509_UNIMPLEMENTED_OPERATION; + } + if (format == HX509_KEY_FORMAT_PKCS8) { + PKCS8PrivateKeyInfo ki; + size_t size; + int ret; + + memset(&ki, 0, sizeof(ki)); + ki.attributes = NULL; /* No localKeyId needed */ + ki.privateKey.data = NULL; + ki.privateKeyAlgorithm.algorithm.components = NULL; + ret = der_parse_hex_heim_integer("00", &ki.version); + if (ret == 0) + ret = _hx509_private_key_oid(context, key, + &ki.privateKeyAlgorithm.algorithm); + if (ret == 0) + /* Re-enter */ + ret = _hx509_private_key_export(context, key, HX509_KEY_FORMAT_DER, + &ki.privateKey); + + /* + * XXX To set ki.privateKeyAlgorithm.parameters we'll need to either + * move this code into the *key->ops->export() functions, or expand + * their signature to allow them to set it for us, or add a method to + * hx509_private_key_ops that allows us to get the parameters from the + * backend. + */ + ki.privateKeyAlgorithm.parameters = NULL; + + if (ret == 0) + ASN1_MALLOC_ENCODE(PKCS8PrivateKeyInfo, data->data, data->length, + &ki, &size, ret); + free_PKCS8PrivateKeyInfo(&ki); + if (ret == 0 && size != data->length) + ret = EINVAL; + if (ret) + hx509_set_error_string(context, 0, ret, + "Private key PKCS#8 encoding failed"); + return ret; + } + return (*key->ops->export)(context, key, format, data); +} + +/* + * + */ + +struct hx509cipher { + const char *name; + int flags; +#define CIPHER_WEAK 1 + const heim_oid *oid; + const AlgorithmIdentifier *(*ai_func)(void); + const EVP_CIPHER *(*evp_func)(void); + int (*get_params)(hx509_context, const hx509_crypto, + const heim_octet_string *, heim_octet_string *); + int (*set_params)(hx509_context, const heim_octet_string *, + hx509_crypto, heim_octet_string *); +}; + +struct hx509_crypto_data { + char *name; + int flags; +#define ALLOW_WEAK 1 + +#define PADDING_NONE 2 +#define PADDING_PKCS7 4 +#define PADDING_FLAGS (2|4) + const struct hx509cipher *cipher; + const EVP_CIPHER *c; + heim_octet_string key; + heim_oid oid; + void *param; +}; + +/* + * + */ + +static unsigned private_rc2_40_oid_data[] = { 127, 1 }; + +static heim_oid asn1_oid_private_rc2_40 = + { 2, private_rc2_40_oid_data }; + +/* + * + */ + +static int +CMSCBCParam_get(hx509_context context, const hx509_crypto crypto, + const heim_octet_string *ivec, heim_octet_string *param) +{ + size_t size; + int ret; + + assert(crypto->param == NULL); + if (ivec == NULL) + return 0; + + ASN1_MALLOC_ENCODE(CMSCBCParameter, param->data, param->length, + ivec, &size, ret); + if (ret == 0 && size != param->length) + _hx509_abort("Internal asn1 encoder failure"); + if (ret) + hx509_clear_error_string(context); + return ret; +} + +static int +CMSCBCParam_set(hx509_context context, const heim_octet_string *param, + hx509_crypto crypto, heim_octet_string *ivec) +{ + int ret; + if (ivec == NULL) + return 0; + + ret = decode_CMSCBCParameter(param->data, param->length, ivec, NULL); + if (ret) + hx509_clear_error_string(context); + + return ret; +} + +struct _RC2_params { + int maximum_effective_key; +}; + +static int +CMSRC2CBCParam_get(hx509_context context, const hx509_crypto crypto, + const heim_octet_string *ivec, heim_octet_string *param) +{ + CMSRC2CBCParameter rc2params; + const struct _RC2_params *p = crypto->param; + int maximum_effective_key = 128; + size_t size; + int ret; + + memset(&rc2params, 0, sizeof(rc2params)); + + if (p) + maximum_effective_key = p->maximum_effective_key; + + switch(maximum_effective_key) { + case 40: + rc2params.rc2ParameterVersion = 160; + break; + case 64: + rc2params.rc2ParameterVersion = 120; + break; + case 128: + rc2params.rc2ParameterVersion = 58; + break; + } + rc2params.iv = *ivec; + + ASN1_MALLOC_ENCODE(CMSRC2CBCParameter, param->data, param->length, + &rc2params, &size, ret); + if (ret == 0 && size != param->length) + _hx509_abort("Internal asn1 encoder failure"); + + return ret; +} + +static int +CMSRC2CBCParam_set(hx509_context context, const heim_octet_string *param, + hx509_crypto crypto, heim_octet_string *ivec) +{ + CMSRC2CBCParameter rc2param; + struct _RC2_params *p; + size_t size; + int ret; + + ret = decode_CMSRC2CBCParameter(param->data, param->length, + &rc2param, &size); + if (ret) { + hx509_clear_error_string(context); + return ret; + } + + p = calloc(1, sizeof(*p)); + if (p == NULL) { + free_CMSRC2CBCParameter(&rc2param); + hx509_clear_error_string(context); + return ENOMEM; + } + switch(rc2param.rc2ParameterVersion) { + case 160: + crypto->c = EVP_rc2_40_cbc(); + p->maximum_effective_key = 40; + break; + case 120: + crypto->c = EVP_rc2_64_cbc(); + p->maximum_effective_key = 64; + break; + case 58: + crypto->c = EVP_rc2_cbc(); + p->maximum_effective_key = 128; + break; + default: + free(p); + free_CMSRC2CBCParameter(&rc2param); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + if (ivec) + ret = der_copy_octet_string(&rc2param.iv, ivec); + free_CMSRC2CBCParameter(&rc2param); + if (ret) { + free(p); + hx509_clear_error_string(context); + } else + crypto->param = p; + + return ret; +} + +/* + * + */ + +static const struct hx509cipher ciphers[] = { + { + "rc2-cbc", + CIPHER_WEAK, + ASN1_OID_ID_PKCS3_RC2_CBC, + NULL, + EVP_rc2_cbc, + CMSRC2CBCParam_get, + CMSRC2CBCParam_set + }, + { + "rc2-cbc", + CIPHER_WEAK, + ASN1_OID_ID_RSADSI_RC2_CBC, + NULL, + EVP_rc2_cbc, + CMSRC2CBCParam_get, + CMSRC2CBCParam_set + }, + { + "rc2-40-cbc", + CIPHER_WEAK, + &asn1_oid_private_rc2_40, + NULL, + EVP_rc2_40_cbc, + CMSRC2CBCParam_get, + CMSRC2CBCParam_set + }, + { + "des-ede3-cbc", + 0, + ASN1_OID_ID_PKCS3_DES_EDE3_CBC, + NULL, + EVP_des_ede3_cbc, + CMSCBCParam_get, + CMSCBCParam_set + }, + { + "des-ede3-cbc", + 0, + ASN1_OID_ID_RSADSI_DES_EDE3_CBC, + hx509_crypto_des_rsdi_ede3_cbc, + EVP_des_ede3_cbc, + CMSCBCParam_get, + CMSCBCParam_set + }, + { + "aes-128-cbc", + 0, + ASN1_OID_ID_AES_128_CBC, + hx509_crypto_aes128_cbc, + EVP_aes_128_cbc, + CMSCBCParam_get, + CMSCBCParam_set + }, + { + "aes-192-cbc", + 0, + ASN1_OID_ID_AES_192_CBC, + NULL, + EVP_aes_192_cbc, + CMSCBCParam_get, + CMSCBCParam_set + }, + { + "aes-256-cbc", + 0, + ASN1_OID_ID_AES_256_CBC, + hx509_crypto_aes256_cbc, + EVP_aes_256_cbc, + CMSCBCParam_get, + CMSCBCParam_set + } +}; + +static const struct hx509cipher * +find_cipher_by_oid(const heim_oid *oid) +{ + size_t i; + + for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++) + if (der_heim_oid_cmp(oid, ciphers[i].oid) == 0) + return &ciphers[i]; + + return NULL; +} + +static const struct hx509cipher * +find_cipher_by_name(const char *name) +{ + size_t i; + + for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++) + if (strcasecmp(name, ciphers[i].name) == 0) + return &ciphers[i]; + + return NULL; +} + + +HX509_LIB_FUNCTION const heim_oid * HX509_LIB_CALL +hx509_crypto_enctype_by_name(const char *name) +{ + const struct hx509cipher *cipher; + + cipher = find_cipher_by_name(name); + if (cipher == NULL) + return NULL; + return cipher->oid; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_crypto_init(hx509_context context, + const char *provider, + const heim_oid *enctype, + hx509_crypto *crypto) +{ + const struct hx509cipher *cipher; + + *crypto = NULL; + + cipher = find_cipher_by_oid(enctype); + if (cipher == NULL) { + hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP, + "Algorithm not supported"); + return HX509_ALG_NOT_SUPP; + } + + *crypto = calloc(1, sizeof(**crypto)); + if (*crypto == NULL) { + hx509_clear_error_string(context); + return ENOMEM; + } + + (*crypto)->flags = PADDING_PKCS7; + (*crypto)->cipher = cipher; + (*crypto)->c = (*cipher->evp_func)(); + + if (der_copy_oid(enctype, &(*crypto)->oid)) { + hx509_crypto_destroy(*crypto); + *crypto = NULL; + hx509_clear_error_string(context); + return ENOMEM; + } + + return 0; +} + +HX509_LIB_FUNCTION const char * HX509_LIB_CALL +hx509_crypto_provider(hx509_crypto crypto) +{ + return "unknown"; +} + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_crypto_destroy(hx509_crypto crypto) +{ + if (crypto->name) + free(crypto->name); + if (crypto->key.data) + free(crypto->key.data); + if (crypto->param) + free(crypto->param); + der_free_oid(&crypto->oid); + memset(crypto, 0, sizeof(*crypto)); + free(crypto); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_crypto_set_key_name(hx509_crypto crypto, const char *name) +{ + return 0; +} + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_crypto_allow_weak(hx509_crypto crypto) +{ + crypto->flags |= ALLOW_WEAK; +} + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_crypto_set_padding(hx509_crypto crypto, int padding_type) +{ + switch (padding_type) { + case HX509_CRYPTO_PADDING_PKCS7: + crypto->flags &= ~PADDING_FLAGS; + crypto->flags |= PADDING_PKCS7; + break; + case HX509_CRYPTO_PADDING_NONE: + crypto->flags &= ~PADDING_FLAGS; + crypto->flags |= PADDING_NONE; + break; + default: + _hx509_abort("Invalid padding"); + } +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_crypto_set_key_data(hx509_crypto crypto, const void *data, size_t length) +{ + if (EVP_CIPHER_key_length(crypto->c) > (int)length) + return HX509_CRYPTO_INTERNAL_ERROR; + + if (crypto->key.data) { + free(crypto->key.data); + crypto->key.data = NULL; + crypto->key.length = 0; + } + crypto->key.data = malloc(length); + if (crypto->key.data == NULL) + return ENOMEM; + memcpy(crypto->key.data, data, length); + crypto->key.length = length; + + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_crypto_set_random_key(hx509_crypto crypto, heim_octet_string *key) +{ + if (crypto->key.data) { + free(crypto->key.data); + crypto->key.length = 0; + } + + crypto->key.length = EVP_CIPHER_key_length(crypto->c); + crypto->key.data = malloc(crypto->key.length); + if (crypto->key.data == NULL) { + crypto->key.length = 0; + return ENOMEM; + } + if (RAND_bytes(crypto->key.data, crypto->key.length) <= 0) { + free(crypto->key.data); + crypto->key.data = NULL; + crypto->key.length = 0; + return HX509_CRYPTO_INTERNAL_ERROR; + } + if (key) + return der_copy_octet_string(&crypto->key, key); + else + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_crypto_set_params(hx509_context context, + hx509_crypto crypto, + const heim_octet_string *param, + heim_octet_string *ivec) +{ + return (*crypto->cipher->set_params)(context, param, crypto, ivec); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_crypto_get_params(hx509_context context, + hx509_crypto crypto, + const heim_octet_string *ivec, + heim_octet_string *param) +{ + return (*crypto->cipher->get_params)(context, crypto, ivec, param); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_crypto_random_iv(hx509_crypto crypto, heim_octet_string *ivec) +{ + ivec->length = EVP_CIPHER_iv_length(crypto->c); + ivec->data = malloc(ivec->length); + if (ivec->data == NULL) { + ivec->length = 0; + return ENOMEM; + } + + if (RAND_bytes(ivec->data, ivec->length) <= 0) { + free(ivec->data); + ivec->data = NULL; + ivec->length = 0; + return HX509_CRYPTO_INTERNAL_ERROR; + } + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_crypto_encrypt(hx509_crypto crypto, + const void *data, + const size_t length, + const heim_octet_string *ivec, + heim_octet_string **ciphertext) +{ + EVP_CIPHER_CTX evp; + size_t padsize, bsize; + int ret; + + *ciphertext = NULL; + + if ((crypto->cipher->flags & CIPHER_WEAK) && + (crypto->flags & ALLOW_WEAK) == 0) + return HX509_CRYPTO_ALGORITHM_BEST_BEFORE; + + assert(EVP_CIPHER_iv_length(crypto->c) == (int)ivec->length); + + EVP_CIPHER_CTX_init(&evp); + + ret = EVP_CipherInit_ex(&evp, crypto->c, NULL, + crypto->key.data, ivec->data, 1); + if (ret != 1) { + EVP_CIPHER_CTX_cleanup(&evp); + ret = HX509_CRYPTO_INTERNAL_ERROR; + goto out; + } + + *ciphertext = calloc(1, sizeof(**ciphertext)); + if (*ciphertext == NULL) { + ret = ENOMEM; + goto out; + } + + assert(crypto->flags & PADDING_FLAGS); + + bsize = EVP_CIPHER_block_size(crypto->c); + padsize = 0; + + if (crypto->flags & PADDING_NONE) { + if (bsize != 1 && (length % bsize) != 0) + return HX509_CMS_PADDING_ERROR; + } else if (crypto->flags & PADDING_PKCS7) { + if (bsize != 1) + padsize = bsize - (length % bsize); + } + + (*ciphertext)->length = length + padsize; + (*ciphertext)->data = malloc(length + padsize); + if ((*ciphertext)->data == NULL) { + ret = ENOMEM; + goto out; + } + + memcpy((*ciphertext)->data, data, length); + if (padsize) { + size_t i; + unsigned char *p = (*ciphertext)->data; + p += length; + for (i = 0; i < padsize; i++) + *p++ = padsize; + } + + ret = EVP_Cipher(&evp, (*ciphertext)->data, + (*ciphertext)->data, + length + padsize); + if (ret != 1) { + ret = HX509_CRYPTO_INTERNAL_ERROR; + goto out; + } + ret = 0; + + out: + if (ret) { + if (*ciphertext) { + if ((*ciphertext)->data) { + free((*ciphertext)->data); + } + free(*ciphertext); + *ciphertext = NULL; + } + } + EVP_CIPHER_CTX_cleanup(&evp); + + return ret; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_crypto_decrypt(hx509_crypto crypto, + const void *data, + const size_t length, + heim_octet_string *ivec, + heim_octet_string *clear) +{ + EVP_CIPHER_CTX evp; + void *idata = NULL; + int ret; + + clear->data = NULL; + clear->length = 0; + + if ((crypto->cipher->flags & CIPHER_WEAK) && + (crypto->flags & ALLOW_WEAK) == 0) + return HX509_CRYPTO_ALGORITHM_BEST_BEFORE; + + if (ivec && EVP_CIPHER_iv_length(crypto->c) < (int)ivec->length) + return HX509_CRYPTO_INTERNAL_ERROR; + + if (crypto->key.data == NULL) + return HX509_CRYPTO_INTERNAL_ERROR; + + if (ivec) + idata = ivec->data; + + EVP_CIPHER_CTX_init(&evp); + + ret = EVP_CipherInit_ex(&evp, crypto->c, NULL, + crypto->key.data, idata, 0); + if (ret != 1) { + EVP_CIPHER_CTX_cleanup(&evp); + return HX509_CRYPTO_INTERNAL_ERROR; + } + + clear->length = length; + clear->data = malloc(length); + if (clear->data == NULL) { + EVP_CIPHER_CTX_cleanup(&evp); + clear->length = 0; + return ENOMEM; + } + + if (EVP_Cipher(&evp, clear->data, data, length) != 1) { + return HX509_CRYPTO_INTERNAL_ERROR; + } + EVP_CIPHER_CTX_cleanup(&evp); + + if ((crypto->flags & PADDING_PKCS7) && EVP_CIPHER_block_size(crypto->c) > 1) { + int padsize; + unsigned char *p; + int j, bsize = EVP_CIPHER_block_size(crypto->c); + + if ((int)clear->length < bsize) { + ret = HX509_CMS_PADDING_ERROR; + goto out; + } + + p = clear->data; + p += clear->length - 1; + padsize = *p; + if (padsize > bsize) { + ret = HX509_CMS_PADDING_ERROR; + goto out; + } + clear->length -= padsize; + for (j = 0; j < padsize; j++) { + if (*p-- != padsize) { + ret = HX509_CMS_PADDING_ERROR; + goto out; + } + } + } + + return 0; + + out: + if (clear->data) + free(clear->data); + clear->data = NULL; + clear->length = 0; + return ret; +} + +typedef int (*PBE_string2key_func)(hx509_context, + const char *, + const heim_octet_string *, + hx509_crypto *, heim_octet_string *, + heim_octet_string *, + const heim_oid *, const EVP_MD *); + +static int +PBE_string2key(hx509_context context, + const char *password, + const heim_octet_string *parameters, + hx509_crypto *crypto, + heim_octet_string *key, heim_octet_string *iv, + const heim_oid *enc_oid, + const EVP_MD *md) +{ + PKCS12_PBEParams p12params; + int passwordlen; + hx509_crypto c; + int iter, saltlen, ret; + unsigned char *salt; + + passwordlen = password ? strlen(password) : 0; + + if (parameters == NULL) + return HX509_ALG_NOT_SUPP; + + ret = decode_PKCS12_PBEParams(parameters->data, + parameters->length, + &p12params, NULL); + if (ret) + goto out; + + if (p12params.iterations) + iter = *p12params.iterations; + else + iter = 1; + salt = p12params.salt.data; + saltlen = p12params.salt.length; + + if (!PKCS12_key_gen (password, passwordlen, salt, saltlen, + PKCS12_KEY_ID, iter, key->length, key->data, md)) { + ret = HX509_CRYPTO_INTERNAL_ERROR; + goto out; + } + + if (!PKCS12_key_gen (password, passwordlen, salt, saltlen, + PKCS12_IV_ID, iter, iv->length, iv->data, md)) { + ret = HX509_CRYPTO_INTERNAL_ERROR; + goto out; + } + + ret = hx509_crypto_init(context, NULL, enc_oid, &c); + if (ret) + goto out; + + hx509_crypto_allow_weak(c); + + ret = hx509_crypto_set_key_data(c, key->data, key->length); + if (ret) { + hx509_crypto_destroy(c); + goto out; + } + + *crypto = c; +out: + free_PKCS12_PBEParams(&p12params); + return ret; +} + +static const heim_oid * +find_string2key(const heim_oid *oid, + const EVP_CIPHER **c, + const EVP_MD **md, + PBE_string2key_func *s2k) +{ + if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND40BITRC2_CBC) == 0) { + *c = EVP_rc2_40_cbc(); + if (*c == NULL) + return NULL; + *md = EVP_sha1(); + if (*md == NULL) + return NULL; + *s2k = PBE_string2key; + return &asn1_oid_private_rc2_40; + } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND128BITRC2_CBC) == 0) { + *c = EVP_rc2_cbc(); + if (*c == NULL) + return NULL; + *md = EVP_sha1(); + if (*md == NULL) + return NULL; + *s2k = PBE_string2key; + return ASN1_OID_ID_PKCS3_RC2_CBC; +#if 0 + } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND40BITRC4) == 0) { + *c = EVP_rc4_40(); + if (*c == NULL) + return NULL; + *md = EVP_sha1(); + if (*md == NULL) + return NULL; + *s2k = PBE_string2key; + return NULL; + } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND128BITRC4) == 0) { + *c = EVP_rc4(); + if (*c == NULL) + return NULL; + *md = EVP_sha1(); + if (*md == NULL) + return NULL; + *s2k = PBE_string2key; + return ASN1_OID_ID_PKCS3_RC4; +#endif + } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND3_KEYTRIPLEDES_CBC) == 0) { + *c = EVP_des_ede3_cbc(); + if (*c == NULL) + return NULL; + *md = EVP_sha1(); + if (*md == NULL) + return NULL; + *s2k = PBE_string2key; + return ASN1_OID_ID_PKCS3_DES_EDE3_CBC; + } + + return NULL; +} + +/* + * + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_pbe_encrypt(hx509_context context, + hx509_lock lock, + const AlgorithmIdentifier *ai, + const heim_octet_string *content, + heim_octet_string *econtent) +{ + hx509_clear_error_string(context); + return EINVAL; +} + +/* + * + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_pbe_decrypt(hx509_context context, + hx509_lock lock, + const AlgorithmIdentifier *ai, + const heim_octet_string *econtent, + heim_octet_string *content) +{ + const struct _hx509_password *pw; + heim_octet_string key, iv; + const heim_oid *enc_oid; + const EVP_CIPHER *c; + const EVP_MD *md; + PBE_string2key_func s2k; + int ret = 0; + size_t i; + + memset(&key, 0, sizeof(key)); + memset(&iv, 0, sizeof(iv)); + + memset(content, 0, sizeof(*content)); + + enc_oid = find_string2key(&ai->algorithm, &c, &md, &s2k); + if (enc_oid == NULL) { + hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP, + "String to key algorithm not supported"); + ret = HX509_ALG_NOT_SUPP; + goto out; + } + + key.length = EVP_CIPHER_key_length(c); + key.data = malloc(key.length); + if (key.data == NULL) { + ret = ENOMEM; + hx509_clear_error_string(context); + goto out; + } + + iv.length = EVP_CIPHER_iv_length(c); + iv.data = malloc(iv.length); + if (iv.data == NULL) { + ret = ENOMEM; + hx509_clear_error_string(context); + goto out; + } + + pw = _hx509_lock_get_passwords(lock); + + ret = HX509_CRYPTO_INTERNAL_ERROR; + for (i = 0; i < pw->len + 1; i++) { + hx509_crypto crypto; + const char *password; + + if (i < pw->len) + password = pw->val[i]; + else if (i < pw->len + 1) + password = ""; + else + password = NULL; + + ret = (*s2k)(context, password, ai->parameters, &crypto, + &key, &iv, enc_oid, md); + if (ret) + goto out; + + ret = hx509_crypto_decrypt(crypto, + econtent->data, + econtent->length, + &iv, + content); + hx509_crypto_destroy(crypto); + if (ret == 0) + goto out; + + } +out: + if (key.data) + der_free_octet_string(&key); + if (iv.data) + der_free_octet_string(&iv); + return ret; +} + +/* + * + */ + + +static int +match_keys_rsa(hx509_cert c, hx509_private_key private_key) +{ + const Certificate *cert; + const SubjectPublicKeyInfo *spi; + RSAPublicKey pk; + RSA *rsa; + size_t size; + int ret; + + if (private_key->private_key.rsa == NULL) + return 0; + + rsa = private_key->private_key.rsa; + if (rsa->d == NULL || rsa->p == NULL || rsa->q == NULL) + return 0; + + cert = _hx509_get_cert(c); + spi = &cert->tbsCertificate.subjectPublicKeyInfo; + + rsa = RSA_new(); + if (rsa == NULL) + return 0; + + ret = decode_RSAPublicKey(spi->subjectPublicKey.data, + spi->subjectPublicKey.length / 8, + &pk, &size); + if (ret) { + RSA_free(rsa); + return 0; + } + rsa->n = heim_int2BN(&pk.modulus); + rsa->e = heim_int2BN(&pk.publicExponent); + + free_RSAPublicKey(&pk); + + rsa->d = BN_dup(private_key->private_key.rsa->d); + rsa->p = BN_dup(private_key->private_key.rsa->p); + rsa->q = BN_dup(private_key->private_key.rsa->q); + rsa->dmp1 = BN_dup(private_key->private_key.rsa->dmp1); + rsa->dmq1 = BN_dup(private_key->private_key.rsa->dmq1); + rsa->iqmp = BN_dup(private_key->private_key.rsa->iqmp); + + if (rsa->n == NULL || rsa->e == NULL || + rsa->d == NULL || rsa->p == NULL|| rsa->q == NULL || + rsa->dmp1 == NULL || rsa->dmq1 == NULL) { + RSA_free(rsa); + return 0; + } + + ret = RSA_check_key(rsa); + RSA_free(rsa); + + return ret == 1; +} + +static int +match_keys_ec(hx509_cert c, hx509_private_key private_key) +{ + return 1; /* XXX use EC_KEY_check_key */ +} + + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_match_keys(hx509_cert c, hx509_private_key key) +{ + if (!key->ops) + return 0; + if (der_heim_oid_cmp(key->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0) + return match_keys_rsa(c, key); + if (der_heim_oid_cmp(key->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) == 0) + return match_keys_ec(c, key); + return 0; + +} + + +static const heim_oid * +find_keytype(const hx509_private_key key) +{ + const struct signature_alg *md; + + if (key == NULL) + return NULL; + + md = _hx509_find_sig_alg(key->signature_alg); + if (md == NULL) + return NULL; + return md->key_oid; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_crypto_select(const hx509_context context, + int type, + const hx509_private_key source, + hx509_peer_info peer, + AlgorithmIdentifier *selected) +{ + const AlgorithmIdentifier *def = NULL; + size_t i, j; + int ret, bits; + + memset(selected, 0, sizeof(*selected)); + + if (type == HX509_SELECT_DIGEST) { + bits = SIG_DIGEST; + if (source) + def = alg_for_privatekey(source, type); + if (def == NULL) + def = _hx509_crypto_default_digest_alg; + } else if (type == HX509_SELECT_PUBLIC_SIG) { + bits = SIG_PUBLIC_SIG; + /* XXX depend on `source´ and `peer´ */ + if (source) + def = alg_for_privatekey(source, type); + if (def == NULL) + def = _hx509_crypto_default_sig_alg; + } else if (type == HX509_SELECT_SECRET_ENC) { + bits = SIG_SECRET; + def = _hx509_crypto_default_secret_alg; + } else { + hx509_set_error_string(context, 0, EINVAL, + "Unknown type %d of selection", type); + return EINVAL; + } + + if (peer) { + const heim_oid *keytype = NULL; + + keytype = find_keytype(source); + + for (i = 0; i < peer->len; i++) { + for (j = 0; sig_algs[j]; j++) { + if ((sig_algs[j]->flags & bits) != bits) + continue; + if (der_heim_oid_cmp(sig_algs[j]->sig_oid, + &peer->val[i].algorithm) != 0) + continue; + if (keytype && sig_algs[j]->key_oid && + der_heim_oid_cmp(keytype, sig_algs[j]->key_oid)) + continue; + + /* found one, use that */ + ret = copy_AlgorithmIdentifier(&peer->val[i], selected); + if (ret) + hx509_clear_error_string(context); + return ret; + } + if (bits & SIG_SECRET) { + const struct hx509cipher *cipher; + + cipher = find_cipher_by_oid(&peer->val[i].algorithm); + if (cipher == NULL) + continue; + if (cipher->ai_func == NULL) + continue; + ret = copy_AlgorithmIdentifier(cipher->ai_func(), selected); + if (ret) + hx509_clear_error_string(context); + return ret; + } + } + } + + /* use default */ + ret = copy_AlgorithmIdentifier(def, selected); + if (ret) + hx509_clear_error_string(context); + return ret; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_crypto_available(hx509_context context, + int type, + hx509_cert source, + AlgorithmIdentifier **val, + unsigned int *plen) +{ + const heim_oid *keytype = NULL; + unsigned int len, i; + void *ptr; + int bits, ret; + + *val = NULL; + + if (type == HX509_SELECT_ALL) { + bits = SIG_DIGEST | SIG_PUBLIC_SIG | SIG_SECRET; + } else if (type == HX509_SELECT_DIGEST) { + bits = SIG_DIGEST; + } else if (type == HX509_SELECT_PUBLIC_SIG) { + bits = SIG_PUBLIC_SIG; + } else { + hx509_set_error_string(context, 0, EINVAL, + "Unknown type %d of available", type); + return EINVAL; + } + + if (source) + keytype = find_keytype(_hx509_cert_private_key(source)); + + len = 0; + for (i = 0; sig_algs[i]; i++) { + if ((sig_algs[i]->flags & bits) == 0) + continue; + if (sig_algs[i]->sig_alg == NULL) + continue; + if (keytype && sig_algs[i]->key_oid && + der_heim_oid_cmp(sig_algs[i]->key_oid, keytype)) + continue; + + /* found one, add that to the list */ + ptr = realloc(*val, sizeof(**val) * (len + 1)); + if (ptr == NULL) + goto out; + *val = ptr; + + ret = copy_AlgorithmIdentifier(sig_algs[i]->sig_alg, &(*val)[len]); + if (ret) + goto out; + len++; + } + + /* Add AES */ + if (bits & SIG_SECRET) { + + for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++) { + + if (ciphers[i].flags & CIPHER_WEAK) + continue; + if (ciphers[i].ai_func == NULL) + continue; + + ptr = realloc(*val, sizeof(**val) * (len + 1)); + if (ptr == NULL) + goto out; + *val = ptr; + + ret = copy_AlgorithmIdentifier((ciphers[i].ai_func)(), &(*val)[len]); + if (ret) + goto out; + len++; + } + } + + *plen = len; + return 0; + +out: + for (i = 0; i < len; i++) + free_AlgorithmIdentifier(&(*val)[i]); + free(*val); + *val = NULL; + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; +} + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_crypto_free_algs(AlgorithmIdentifier *val, + unsigned int len) +{ + unsigned int i; + for (i = 0; i < len; i++) + free_AlgorithmIdentifier(&val[i]); + free(val); +} diff --git a/third_party/heimdal/lib/hx509/data/PKITS.pdf b/third_party/heimdal/lib/hx509/data/PKITS.pdf Binary files differnew file mode 100644 index 0000000..3a56862 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/PKITS.pdf diff --git a/third_party/heimdal/lib/hx509/data/PKITS_data.zip b/third_party/heimdal/lib/hx509/data/PKITS_data.zip Binary files differnew file mode 100644 index 0000000..50d6fbb --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/PKITS_data.zip diff --git a/third_party/heimdal/lib/hx509/data/bleichenbacher-bad.pem b/third_party/heimdal/lib/hx509/data/bleichenbacher-bad.pem new file mode 100644 index 0000000..2c71932 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/bleichenbacher-bad.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBsDCCAVoCAQYwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCQVUxEzARBgNV +BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMSMwIQYD +VQQDExpTZXJ2ZXIgdGVzdCBjZXJ0ICg1MTIgYml0KTAeFw0wNjA5MTEyMzU4NTVa +Fw0wNjEwMTEyMzU4NTVaMGMxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpRdWVlbnNs +YW5kMRowGAYDVQQKExFDcnlwdFNvZnQgUHR5IEx0ZDEjMCEGA1UEAxMaU2VydmVy +IHRlc3QgY2VydCAoNTEyIGJpdCkwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAn7PD +hCeV/xIxUg8V70YRxK2A5jZbD92A12GN4PxyRQk0/lVmRUNMaJdq/qigpd9feP/u +12S4PwTLb/8q/v657QIDAQABMA0GCSqGSIb3DQEBBQUAA0EAbynCRIlUQgaqyNgU +DF6P14yRKUtX8akOP2TwStaSiVf/akYqfLFm3UGka5XbPj4rifrZ0/sOoZEEBvHQ +e20sRA== +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/bleichenbacher-good.pem b/third_party/heimdal/lib/hx509/data/bleichenbacher-good.pem new file mode 100644 index 0000000..409147b --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/bleichenbacher-good.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBsDCCAVoCAQYwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCQVUxEzARBgNV +BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMSMwIQYD +VQQDExpTZXJ2ZXIgdGVzdCBjZXJ0ICg1MTIgYml0KTAeFw0wNjA5MTEyMzU5MDJa +Fw0wNjEwMTEyMzU5MDJaMGMxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpRdWVlbnNs +YW5kMRowGAYDVQQKExFDcnlwdFNvZnQgUHR5IEx0ZDEjMCEGA1UEAxMaU2VydmVy +IHRlc3QgY2VydCAoNTEyIGJpdCkwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAn7PD +hCeV/xIxUg8V70YRxK2A5jZbD92A12GN4PxyRQk0/lVmRUNMaJdq/qigpd9feP/u +12S4PwTLb/8q/v657QIDAQABMA0GCSqGSIb3DQEBBQUAA0EAc+fnj0rB2CYautG2 +4itiMOU4SN6JFTFDCTU/Gb5aR/Fiu7HJkuE5yGEnTdnwcId/T9sTW251yzCc1e2z +rHX/kw== +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/bleichenbacher-sf-pad-correct.pem b/third_party/heimdal/lib/hx509/data/bleichenbacher-sf-pad-correct.pem new file mode 100644 index 0000000..3e73f5d --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/bleichenbacher-sf-pad-correct.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICgzCCAWugAwIBAgIBFzANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl +MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp +U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYw +ODE5MTY1MTMwWhcNMDYxMDE4MTY1MTMwWjARMQ8wDQYDVQQDEwZIYWNrZXIwgZ8w +DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKSu6ChWttBsOpaBrYf4PzyCGNe6DuE7 +rmq4CMskdz8uiAJ3wVd8jGsjdeY4YzoXSVp+9mEF6XqNgyDf8Ub3kNgPYxvJ28lg +QVpd5RdGWXHo14LWBTD1mtFkCiAhVlATsVNI/tjv2tv7Jp8EsylbDHe7hslA0rns +Rr2cS9bvpM03AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEF +BQADggEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADLL/Up63HkFWD15INcW +Xd1nZGI+gO/whm58ICyJ1Js7ON6N4NyBTwe8513CvdOlOdG/Ctmy2gxEE47HhEed +ST8AUooI0ey599t84P20gGRuOYIjr7c= +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/ca.crt b/third_party/heimdal/lib/hx509/data/ca.crt new file mode 100644 index 0000000..7aa8bcf --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/ca.crt @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFczCCA1ugAwIBAgIJAI34CtjBcJHEMA0GCSqGSIb3DQEBCwUAMCoxGzAZBgNV +BAMMEmh4NTA5IFRlc3QgUm9vdCBDQTELMAkGA1UEBhMCU0UwIBcNMTkwMzIyMjIy +NTAxWhgPMjUxODExMjEyMjI1MDFaMCoxGzAZBgNVBAMMEmh4NTA5IFRlc3QgUm9v +dCBDQTELMAkGA1UEBhMCU0UwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQDE4gbVQ/vlPFU2W62rukqiUkJ/EIDo1HE4r+xpxO12Ke45NtqSep0d2FfSvEu8 +dhot1jWIkijF7B/bFuB0LyFryCAV/zlU9rLoadCmur5ONIgXRm7eW19wxo5YRD4C +A1IRwvT+Axz0TC3eyquUN1C0r7ZWbiOY8uQy3Sjfar16Z3TtqlKgo4R/yF7dIPJO +OVHaznC+xsfLsYE2r9PqbTjBF3O1pIhwV9oA3tfs23EtvcZBP3y3LSsjnKaF0b/N +XmjLNW9hbmAfN+16TEMOlVZvBjUPO3CC/GU0PJzm1/FqyzXWeRx5FZNi7fCPKg8J +9QDAgK5mMn+ZPazuUt70uxUFrnRLCjCia/TgC+t2d+3AqsnRlYnLYDv/MeP/QwqH +GK3+WuAS6uqXZMtilDhY+oiMTZ4vDHvwzJ5q3UhIpWXj5cSGWAxQurKgUsjT9sta +gGmXlBauMYSzFM5T+TXica1qE7dNXjXr2sTy9BHIp+aWJuGkX9rSx8tHwbkIkVTp +4UCZ+QoxBRaSmiuyFPM77yg6wZBuSuRRN/BNKvAhuJaE1MdA+vobbyyNbv56MU0+ +WI4ucD+b08JmJp3k+fgM0fKXBQlEL4mp7zeUoLmC1yCy48Zk1foPZTRH9pIGB/zU +z4B8o20NmereB9bX0IjJ6eqMDqvAZWZ99Nf16Q3X88T88wIDAQABo4GZMIGWMB0G +A1UdDgQWBBRTuMwJxp9C6tXkdCC0Ze1o+J21BTBaBgNVHSMEUzBRgBRTuMwJxp9C +6tXkdCC0Ze1o+J21BaEupCwwKjEbMBkGA1UEAwwSaHg1MDkgVGVzdCBSb290IENB +MQswCQYDVQQGEwJTRYIJAI34CtjBcJHEMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQD +AgHmMA0GCSqGSIb3DQEBCwUAA4ICAQCdea8Tx/1vuQCqn2AOmIzEO9xgmaY3opl9 +0Px82DafNuFFJu9WlPrsKeADtSqpA/MwBjL8K+T3dhL4Bxhq8jed0gGsS3C3xFTl +/RJbnFiLuveMErPTEtxaRYpa3oibQ15eJbDq533Is1x8oeK6NnHB6St3nboST0f3 +6SeAsoeHrI16eUEJQ3UKJYJlxATEqOpeaWwdlT6jF9u0WyENz0ijD0b9FPY/zq6D +zx47Zd5F6aisrtKNXFjB9/oHV6jOh9OGxz6WfT1z2AZ+69jEm+xE8coq4nyWcJrS +cf7ENBIw1Rknpxk3/H1p0q+Zze5/JBYlKOtEML1dwRIRquVgfhcI/tOq7m5jUxTl +/6dW8FCnuEFBnUvUrZ0Hv3g2jvHElpPjYkLwZyKFYyvY/G+xCZAiqaYZ2kQqRmti +KvSfh8fJlV2Jj2aDI1I4JjACG7LYBe7WXCs7TccRrhnx/RUY7cpJwEQrIOKBq8wx +DD58oPgvkmNPP5lZcFARjnWcY8xS9KzT+KaZWM3ZPefg3Vk//3HfwZfDE3Y7IMgu +quuLcpeGtMDyurnm6piUdPITt8yW+MMJR8V+PeF0zLdN4dA0nuJpZWZ3fvnevmAL +jh/ia0LuzkhVSj1R1dXXopZevazh/tmAuKU9BbeYGvwI1RFXVvyzpGRfMbgaze3Q +tIrreKeFxg== +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/ca.key b/third_party/heimdal/lib/hx509/data/ca.key new file mode 100644 index 0000000..83cff75 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/ca.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDE4gbVQ/vlPFU2 +W62rukqiUkJ/EIDo1HE4r+xpxO12Ke45NtqSep0d2FfSvEu8dhot1jWIkijF7B/b +FuB0LyFryCAV/zlU9rLoadCmur5ONIgXRm7eW19wxo5YRD4CA1IRwvT+Axz0TC3e +yquUN1C0r7ZWbiOY8uQy3Sjfar16Z3TtqlKgo4R/yF7dIPJOOVHaznC+xsfLsYE2 +r9PqbTjBF3O1pIhwV9oA3tfs23EtvcZBP3y3LSsjnKaF0b/NXmjLNW9hbmAfN+16 +TEMOlVZvBjUPO3CC/GU0PJzm1/FqyzXWeRx5FZNi7fCPKg8J9QDAgK5mMn+ZPazu +Ut70uxUFrnRLCjCia/TgC+t2d+3AqsnRlYnLYDv/MeP/QwqHGK3+WuAS6uqXZMti +lDhY+oiMTZ4vDHvwzJ5q3UhIpWXj5cSGWAxQurKgUsjT9stagGmXlBauMYSzFM5T ++TXica1qE7dNXjXr2sTy9BHIp+aWJuGkX9rSx8tHwbkIkVTp4UCZ+QoxBRaSmiuy +FPM77yg6wZBuSuRRN/BNKvAhuJaE1MdA+vobbyyNbv56MU0+WI4ucD+b08JmJp3k ++fgM0fKXBQlEL4mp7zeUoLmC1yCy48Zk1foPZTRH9pIGB/zUz4B8o20NmereB9bX +0IjJ6eqMDqvAZWZ99Nf16Q3X88T88wIDAQABAoICAQCD8TXDFpxpM9WnaCkrPN1n +itklbln1rulxo/Q7rc21ssQDc89m+uTwa1vvzmCzHDLPJQ8bR1gry+JNYTdqpWsw +YB2goDo7xlh/iOpb0ipXHr1VW85RFcsQOQCMBq/HiZImdRDaahutXKAg/pGd8rQT +Yu4/XfBdP+nObIhHsbDppwules+E+BCD0jRA3SOFaMSCbncAYxbiW0LM82iBYlD2 +llDlGi6Vm0pt6umpwiZHETcb4wAhghO2+fRfGgIAD5ULGfRaxy2DvmdX3mPSEiKq +pO5KFvt/zMXGDBjaWz1e5HBgGyoJu3vagLsGNpl9gsPOPm6h7pW0jLCnxsHEINwk +lGbhCR9ubaZMCNuwEppPNeusURG35XiSEHC4fBPhlG6pB737a6ih/w9dwOkLuijJ +X3vOaVj2K5waExi72uij+GnZBylemOTAy9lE3xlUzhO74h9F8DuoJHMxXKU5a24L +/hmnnIYHOJpHQIfcfkMIx9VuG/qsug+DdOxlgByT6hbkRbX2gGSP3iqy7XUnb2g0 +3QQdyQpz8wJ2x568EAAC0HKhQj2fcL1L5lpM5xpbg6s87o50reMhcAogb2mGjx3Q +r8u9PJeYgJ5FOqu0zLbenWkb4OLtLz6kHhOdimkCrybL+bLQFdl9lNAOqgVuJxyT +NaClP+v9lAACBkONihU8AQKCAQEA9hxExY0NXFDZHiLq4M4DG79BthLWLi4QFZI5 +2vpzrS5kT90rptAzBenTBWdUifAI8JPkq2R8VKB8j7F5YELQ9UTmoT+qMGEslQ1p +RTE8fZln6UhLUIv5tTwhL6Afbs2Faz7Vd7rUq9eUkyxsjxtZe5cPH1dGplx0iPQI +QQ1OasSWc8TmZWXRvcRWe5vWiJLFZKt6fJZWYyBBvu8L7PZ6QR5Oa2EO1UTPPX+W +7+BwsoH9Bguv+hYliKEReN8SIfOF9E/OElrNooy7eANFTQ3pNEou68rqpzX4jgdW +G4Nnsu9rkO8K+bb+/MLBvdxrEiKrNb+xwcVOFaJNqz6aNMC14QKCAQEAzMtbIpig +dLUha3QXrXIsEjH/hlGx0c6Q9VH/toQbBNE4LOrS4QlurX3iRz79tNYLYdwLrZ2Q ++tK31/ilX/hGIiA1w6fHcrQokddMJhhGoR6nSUiybs+75Ac01xHDSYXCo/YOkr8m +HOtRWi+0qJqzU4sticPwi2YStM6L2gNpEDU9FQTG/wgLLHPxDEjRpkhmgQbt8nEQ +M+amXK1othrZVSTJl1hREF11DkzhkZYyGgY4ifAyAOPW7z5K0nS2drV8PExFSkr+ +2eriVvavu/40WbvadhTy1cyVL7N3svzY34TgwqsXX1Stz8dQBa+uImt9gxmZIK9I +reONiErKBhClUwKCAQEAjY1IyM8OBjDCECFJMq+K/iSM6OoAomMAAUgvWpF+gvcR +3xV4i+Nn1VjddFgwOX4Dxktp1GJhWFNOEV+kTgdgJBHTDJ+PhW/+smQaTh+5iQv4 +xiY8m0FHCERjWf8g1RwERuDG6qxcsdG2tMdyUQUL/JevrPkHu5ulszeYn8HFfoc/ +eaqgUWW0sw8AJuxFAhxYyEQQmSPm3/Cnn+fh1hMV0epadExIucVv5RFDgQh4CVPW +cem6935RbDon0HuM9FYaj6BvCAOODpYfJTHMZDtCDD82qYv2VuIl6ZqynfSAalxm +Y9/5UhM8qahiwo7KTo3+J1XwKWEQPkUxovLIwtqsQQKCAQEAgMgwWyUXYcy1Y1jx +usRdKmP+h3zAEWuQhHQ4FZIlW3YlmTlhutmvm7HZpWvbJuii57r0LQ00qkXwDgPy +GtOJZtRSeuL67QqVqIB3Bk2lvJQGJnNsoXpIcTCG7efhok5XA7wrleRWF0FzOv9c +39nIgvS2gjeRAFgD02c/Uq1qWCLicmE6sg1g2WdfYZY5IBPPQbwVzauDwN9+JjF1 +824W1Q/5JQ8Iiv36Ki/2eRK2Ft9qlnNRPnYIJxJJAucaBrRBl7luqTVX5blq87zU +7acBTJxw2Gh7/C5WclStJQUTbBunK0NjwzMAyfRQQgMjwclOeC6UuJUBYzgBPH+r +Yvz8uQKCAQA8WchJ0UQmOP98voo0cnIX0lcZcddwzdsZm78p1PrXqmsrxnlmRILA +wZ5okzIzEqu1Xltu5DS/CAAWdRkY/2LFGty1dW5UR47xsWE7fMf4dbPeOcBxgfh4 +sQgG7KcWY9mw3PZ4PmPP63nRC/1Ws/+dlvpNA77BjyHH7laTVZbUadS/0bCzhJG0 +RW27r5UcPV8IhKTNU8iOxvaN2U0N2RaaxZ8AaYj8UEeMlFp91DXYa5SCWY1yM0c7 +QYpO3EtSLj+ECk09lDzQBPUo4jzb5CoTFYDEdXr8Rt4I/r03fkOwHslWUzXVyqRe +xC/DrYbFBHh4yQWuQPsmCbi6OkGKDvwA +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/crl1.crl b/third_party/heimdal/lib/hx509/data/crl1.crl new file mode 100644 index 0000000..575f80e --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/crl1.crl @@ -0,0 +1,16 @@ +-----BEGIN X509 CRL----- +MIIChTBvMA0GCSqGSIb3DQEBBQUAMCoxGzAZBgNVBAMMEmh4NTA5IFRlc3QgUm9v +dCBDQTELMAkGA1UEBhMCU0UXDTE5MDMyMjIyMjUxNloXDTI5MDEyODIyMjUxNlow +FDASAgEDFw0xOTAzMjIyMjI1MTZaMA0GCSqGSIb3DQEBBQUAA4ICAQBCM4u2dByD +hPsQUpPAPsZ/a7tPdvkgmcLtk2CFhtJqtDBT96SAr0tVpcpIbZoB0tH/MvJfhAaR +AOLrgdmrwlKaIbq3uyEDIghRlRiG2WXX+gsP9yK1xS6AuQnXS8Pnyng0xo2V8fMy +UCN+gKvO70O6dqcDApU1Tt5jxkPFACBYSSMsuunrjWGuttKGebJJGeBzU+PYt7bZ +7CT2BgsLgl5J2DL6KO9tGjDmlGKKC2joF1PDkjzbIfs389eyOZqJu/3Q4EtBFzad +Yz0DAEDzDrn7dj53NJp6dxbqOM86woak37dtDG5Mwu8KTQEGpfsqdofQf39nluJu +70NHJrXP+9IQ7Tvb3bakZbyigw7J9PBXaHyImXN/gejYD/FQjghnmS2QU72JsSKT +3nAN3I6MRAEIhoaxForCl3f+uHgtvQBBITSIUdnGaTZnI0mXrkHS9H4eWWJREZbc +wBqKGZxbfy8ZbPaKv75Zzj0ZMns7vNybUqLEE/OcwrEjd/pCLwWZ6KzgtS1t22TU +o3H26GNLzMQvg/1dVsRZWrkWxAjVNHtUIXXbmBOvSii3BX7jPIfH1bCZrfsl0xrS +BsqhtIZj74hyTV1FX79CdFu0Ag/ugtzY4K8rdIu9kaPe2Ju6ulQBtpmCK++H7szP +48fJOwV1aKzJGVCH61kSGc8ljyGjDEDn4Q== +-----END X509 CRL----- diff --git a/third_party/heimdal/lib/hx509/data/crl1.der b/third_party/heimdal/lib/hx509/data/crl1.der Binary files differnew file mode 100644 index 0000000..a667423 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/crl1.der diff --git a/third_party/heimdal/lib/hx509/data/eccurve.pem b/third_party/heimdal/lib/hx509/data/eccurve.pem new file mode 100644 index 0000000..a76e47d --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/eccurve.pem @@ -0,0 +1,3 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- diff --git a/third_party/heimdal/lib/hx509/data/gen-req.sh b/third_party/heimdal/lib/hx509/data/gen-req.sh new file mode 100755 index 0000000..09f0dfb --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/gen-req.sh @@ -0,0 +1,360 @@ +#!/bin/sh +# $Id$ +# +# This script need openssl 0.9.8a or newer, so it can parse the +# otherName section for pkinit certificates. +# + +openssl=openssl + +# workaround until openssl -objects lands +if ${openssl} version | grep '^OpenSSL 1\.[1-9]' >/dev/null ; then + config=openssl.1.1.cnf +else + config=openssl.1.0.cnf +fi + +gen_cert() +{ + keytype=${6:-rsa:4096} + ${openssl} req \ + -new \ + -subj "$1" \ + -config ${config} \ + -newkey $keytype \ + -sha1 \ + -nodes \ + -keyout out.key \ + -out cert.req > /dev/null 2>/dev/null + + if [ "$3" = "ca" ] ; then + ${openssl} x509 \ + -req \ + -days 182500 \ + -in cert.req \ + -extfile ${config} \ + -extensions $4 \ + -signkey out.key \ + -out cert.crt + + ln -s ca.crt `${openssl} x509 -hash -noout -in cert.crt`.0 + + name=$3 + + elif [ "$3" = "proxy" ] ; then + + ${openssl} x509 \ + -req \ + -in cert.req \ + -days 182500 \ + -out cert.crt \ + -CA $2.crt \ + -CAkey $2.key \ + -CAcreateserial \ + -extfile ${config} \ + -extensions $4 + + name=$5 + else + + ${openssl} ca \ + -name $4 \ + -days 182500 \ + -cert $2.crt \ + -keyfile $2.key \ + -in cert.req \ + -out cert.crt \ + -outdir . \ + -batch \ + -config ${config} + + name=$3 + fi + + mv cert.crt $name.crt + mv out.key $name.key +} + +echo "01" > serial +> index.txt +rm -f *.0 + +gen_cert "/CN=hx509 Test Root CA/C=SE" "root" "ca" "v3_ca" +gen_cert "/CN=OCSP responder/C=SE" "ca" "ocsp-responder" "ocsp" +gen_cert "/CN=Test cert/C=SE" "ca" "test" "usr" +gen_cert "/CN=Revoke cert/C=SE" "ca" "revoke" "usr" +gen_cert "/CN=Test cert KeyEncipherment/C=SE" "ca" "test-ke-only" "usr_ke" +gen_cert "/CN=Test cert DigitalSignature/C=SE" "ca" "test-ds-only" "usr_ds" +gen_cert "/CN=pkinit/C=SE" "ca" "pkinit" "pkinit_client" +$openssl ecparam -name secp256r1 -out eccurve.pem +gen_cert "/CN=pkinit-ec/C=SE" "ca" "pkinit-ec" "pkinit_client" "XXX" ec:eccurve.pem +gen_cert "/C=SE/CN=pkinit/CN=pkinit-proxy" "pkinit" "proxy" "proxy_cert" pkinit-proxy +gen_cert "/CN=kdc/C=SE" "ca" "kdc" "pkinit_kdc" +gen_cert "/CN=www.test.h5l.se/C=SE" "ca" "https" "https" +gen_cert "/CN=Sub CA/C=SE" "ca" "sub-ca" "subca" +gen_cert "/CN=Test sub cert/C=SE" "sub-ca" "sub-cert" "usr" +gen_cert "/C=SE/CN=Test cert/CN=proxy" "test" "proxy" "proxy_cert" proxy-test +gen_cert "/C=SE/CN=Test cert/CN=proxy/CN=child" "proxy-test" "proxy" "proxy_cert" proxy-level-test +gen_cert "/C=SE/CN=Test cert/CN=no-proxy" "test" "proxy" "usr_cert" no-proxy-test +gen_cert "/C=SE/CN=Test cert/CN=proxy10" "test" "proxy" "proxy10_cert" proxy10-test +gen_cert "/C=SE/CN=Test cert/CN=proxy10/CN=child" "proxy10-test" "proxy" "proxy10_cert" proxy10-child-test +gen_cert "/C=SE/CN=Test cert/CN=proxy10/CN=child/CN=child" "proxy10-child-test" "proxy" "proxy10_cert" proxy10-child-child-test + + +# combine +cat sub-ca.crt ca.crt > sub-ca-combined.crt +cat test.crt test.key > test.combined.crt +cat pkinit-proxy.crt pkinit.crt > pkinit-proxy-chain.crt + +# password protected key +${openssl} rsa -in test.key -aes256 -passout pass:foobar -out test-pw.key +${openssl} rsa -in pkinit.key -aes256 -passout pass:foo -out pkinit-pw.key + + +${openssl} ca \ + -name usr \ + -cert ca.crt \ + -keyfile ca.key \ + -revoke revoke.crt \ + -config ${config} + +${openssl} pkcs12 \ + -export \ + -in test.crt \ + -inkey test.key \ + -passout pass:foobar \ + -out test.p12 \ + -name "friendlyname-test" \ + -certfile ca.crt \ + -caname ca + +${openssl} pkcs12 \ + -export \ + -in sub-cert.crt \ + -inkey sub-cert.key \ + -passout pass:foobar \ + -out sub-cert.p12 \ + -name "friendlyname-sub-cert" \ + -certfile sub-ca-combined.crt \ + -caname sub-ca \ + -caname ca + +${openssl} pkcs12 \ + -keypbe NONE \ + -certpbe NONE \ + -export \ + -in test.crt \ + -inkey test.key \ + -passout pass:foobar \ + -out test-nopw.p12 \ + -name "friendlyname-cert" \ + -certfile ca.crt \ + -caname ca + +${openssl} smime \ + -sign \ + -nodetach \ + -binary \ + -in static-file \ + -signer test.crt \ + -inkey test.key \ + -outform DER \ + -out test-signed-data + +${openssl} smime \ + -sign \ + -nodetach \ + -binary \ + -in static-file \ + -signer test.crt \ + -inkey test.key \ + -noattr \ + -outform DER \ + -out test-signed-data-noattr + +${openssl} smime \ + -sign \ + -nodetach \ + -binary \ + -in static-file \ + -signer test.crt \ + -inkey test.key \ + -noattr \ + -nocerts \ + -outform DER \ + -out test-signed-data-noattr-nocerts + +${openssl} smime \ + -sign \ + -md sha1 \ + -nodetach \ + -binary \ + -in static-file \ + -signer test.crt \ + -inkey test.key \ + -outform DER \ + -out test-signed-sha-1 + +${openssl} smime \ + -sign \ + -md sha256 \ + -nodetach \ + -binary \ + -in static-file \ + -signer test.crt \ + -inkey test.key \ + -outform DER \ + -out test-signed-sha-256 + +${openssl} smime \ + -sign \ + -md sha512 \ + -nodetach \ + -binary \ + -in static-file \ + -signer test.crt \ + -inkey test.key \ + -outform DER \ + -out test-signed-sha-512 + + +${openssl} smime \ + -encrypt \ + -nodetach \ + -binary \ + -in static-file \ + -outform DER \ + -out test-enveloped-rc2-40 \ + -rc2-40 \ + test.crt + +${openssl} smime \ + -encrypt \ + -nodetach \ + -binary \ + -in static-file \ + -outform DER \ + -out test-enveloped-rc2-64 \ + -rc2-64 \ + test.crt + +${openssl} smime \ + -encrypt \ + -nodetach \ + -binary \ + -in static-file \ + -outform DER \ + -out test-enveloped-rc2-128 \ + -rc2-128 \ + test.crt + +${openssl} smime \ + -encrypt \ + -nodetach \ + -binary \ + -in static-file \ + -outform DER \ + -out test-enveloped-des \ + -des \ + test.crt + +${openssl} smime \ + -encrypt \ + -nodetach \ + -binary \ + -in static-file \ + -outform DER \ + -out test-enveloped-des-ede3 \ + -des3 \ + test.crt + +${openssl} smime \ + -encrypt \ + -nodetach \ + -binary \ + -in static-file \ + -outform DER \ + -out test-enveloped-aes-128 \ + -aes128 \ + test.crt + +${openssl} smime \ + -encrypt \ + -nodetach \ + -binary \ + -in static-file \ + -outform DER \ + -out test-enveloped-aes-256 \ + -aes256 \ + test.crt + +echo ocsp requests + +${openssl} ocsp \ + -issuer ca.crt \ + -cert test.crt \ + -reqout ocsp-req1.der + +${openssl} ocsp \ + -index index.txt \ + -rsigner ocsp-responder.crt \ + -rkey ocsp-responder.key \ + -CA ca.crt \ + -reqin ocsp-req1.der \ + -noverify \ + -respout ocsp-resp1-ocsp.der + +${openssl} ocsp \ + -index index.txt \ + -rsigner ca.crt \ + -rkey ca.key \ + -CA ca.crt \ + -reqin ocsp-req1.der \ + -noverify \ + -respout ocsp-resp1-ca.der + +${openssl} ocsp \ + -index index.txt \ + -rsigner ocsp-responder.crt \ + -rkey ocsp-responder.key \ + -CA ca.crt \ + -resp_no_certs \ + -reqin ocsp-req1.der \ + -noverify \ + -respout ocsp-resp1-ocsp-no-cert.der + +${openssl} ocsp \ + -index index.txt \ + -rsigner ocsp-responder.crt \ + -rkey ocsp-responder.key \ + -CA ca.crt \ + -reqin ocsp-req1.der \ + -resp_key_id \ + -noverify \ + -respout ocsp-resp1-keyhash.der + +${openssl} ocsp \ + -issuer ca.crt \ + -cert revoke.crt \ + -reqout ocsp-req2.der + +${openssl} ocsp \ + -index index.txt \ + -rsigner ocsp-responder.crt \ + -rkey ocsp-responder.key \ + -CA ca.crt \ + -reqin ocsp-req2.der \ + -noverify \ + -respout ocsp-resp2.der + +${openssl} ca \ + -gencrl \ + -name usr \ + -crldays 3600 \ + -keyfile ca.key \ + -cert ca.crt \ + -crl_reason superseded \ + -out crl1.crl \ + -config ${config} + +${openssl} crl -in crl1.crl -outform der -out crl1.der diff --git a/third_party/heimdal/lib/hx509/data/https.crt b/third_party/heimdal/lib/hx509/data/https.crt new file mode 100644 index 0000000..54d5df1 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/https.crt @@ -0,0 +1,116 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 9 (0x9) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Mar 22 22:25:10 2019 GMT + Not After : Nov 21 22:25:10 2518 GMT + Subject: C=SE, CN=www.test.h5l.se + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:bb:ca:85:9c:3d:6b:5a:21:1b:2c:84:35:48:37: + bc:13:62:93:ff:7b:be:49:40:e2:36:b5:7a:54:a4: + e3:0f:b1:87:29:de:6b:7d:86:ec:b6:25:c5:9c:dc: + 13:06:57:4c:80:1b:86:f0:ac:e6:64:8f:aa:63:cc: + 28:49:5c:84:09:b8:0f:31:99:dd:36:d2:42:b5:aa: + df:31:f6:27:ca:c2:4c:50:11:5b:01:94:17:da:2a: + 5c:21:e5:b5:81:23:69:3e:4f:1d:08:48:95:57:30: + 77:96:ae:9b:78:87:10:e4:6d:90:e8:78:ad:19:41: + 3d:b8:91:1c:b6:04:78:52:e5:e4:3f:28:df:01:13: + da:aa:cb:24:cf:f5:93:f9:02:b8:c5:dc:47:fb:79: + e5:de:9e:19:b3:28:ab:2d:bd:73:48:0f:71:0a:b6: + 81:5a:6d:02:6d:9c:c8:c3:14:d5:82:bf:19:b8:d0: + 6f:58:32:6c:76:91:f3:07:6b:25:4a:59:f4:2d:c9: + 8d:da:ee:cc:30:5b:5b:d8:f3:0d:63:28:8d:9c:df: + 21:b5:3a:41:e0:55:d0:5f:f1:32:45:0b:6b:40:b6: + d8:43:0c:7b:28:3d:2d:7c:40:19:a2:e0:d6:a2:0b: + 32:65:a3:81:e9:1c:e5:6a:f6:61:7c:66:fa:c6:10: + bf:5d:1d:d9:c1:1a:67:fb:a0:43:15:ff:f5:40:5a: + 0c:8a:4b:48:38:d5:c7:77:48:19:f7:21:de:73:17: + 97:cf:03:d7:c3:84:22:38:ae:f2:be:d2:61:af:37: + 38:31:41:01:97:58:93:ba:80:da:bb:00:33:a8:2b: + 98:34:80:8b:00:1e:83:02:c4:26:3f:5c:51:a9:29: + e3:ac:b1:36:31:57:87:43:94:57:3a:17:f4:6d:34: + bf:23:b6:a2:56:d2:b7:72:7e:35:34:d9:58:46:c1: + 64:2d:3f:e7:ff:e4:fd:42:11:d9:04:98:ba:9d:88: + ec:e7:ae:bb:11:42:fd:00:cb:24:17:27:94:2c:a0: + 34:df:18:8b:7a:bc:39:55:6c:02:3b:44:cf:a4:42: + f3:e3:81:5b:d6:90:8e:78:d7:3f:4c:ef:6c:de:4d: + 7e:41:ce:87:8f:c0:38:a4:57:05:63:32:85:c3:de: + 88:aa:8c:0b:04:df:c3:86:64:4c:19:91:e1:e4:b2: + f8:f6:f3:fe:93:c3:3e:c1:b1:74:b4:72:ff:88:94: + 8d:34:a3:b0:9d:55:aa:fe:bc:bc:41:55:49:8a:f1: + ee:dd:fa:0e:a1:fa:b9:71:a7:d5:fc:b7:fc:ab:c2: + af:8f:bd:6e:48:ec:54:f0:f8:a8:b4:d7:6c:11:0e: + f9:16:ab + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + AA:3C:0D:95:CD:14:0A:9C:A5:2D:09:6E:EE:5B:43:A9:AF:3F:6E:54 + Signature Algorithm: sha1WithRSAEncryption + a3:ec:06:1b:66:b3:cb:a3:12:38:ef:30:dc:a6:a1:fc:d3:52: + d0:73:c8:a9:4d:0b:8e:02:2a:08:a6:4f:55:41:2f:46:2b:cf: + e9:04:07:9d:42:47:0d:88:64:1f:39:ae:d7:9b:30:43:47:f9: + ba:96:a8:2f:7a:6e:4b:22:9c:65:c7:9c:8c:c6:d2:f2:5f:a9: + fd:de:eb:9e:7a:13:b8:22:0c:59:15:90:ba:65:b7:08:3d:dd: + 2e:e2:09:be:47:53:25:0a:8c:d3:e0:78:e9:1a:15:8e:32:b2: + 5f:76:e1:68:3c:2f:33:3f:38:17:ff:3b:ad:43:b7:0e:87:08: + 97:6b:8d:a7:6c:3b:de:1a:18:3d:5b:74:0b:87:03:8a:49:b0: + 22:84:2a:72:f1:01:c3:b5:55:9e:4a:56:c1:96:6c:ba:9c:eb: + 58:ce:4e:53:fd:b8:99:02:c1:d5:62:ef:b5:44:73:1c:c6:4f: + 26:f9:8d:6b:e9:58:be:3c:4a:56:ef:65:6a:f5:71:1c:3b:8e: + f4:ae:43:44:ab:26:80:41:da:a9:6b:9b:63:49:bc:39:76:3b: + 1e:fe:a5:24:0e:4c:59:51:9d:47:c4:ce:2b:90:65:e8:f8:ae: + ab:aa:14:cc:d2:4a:cf:85:20:40:dd:80:49:ea:7c:98:04:ee: + 57:41:e6:bc:13:fc:28:5e:08:5c:ee:fa:1b:72:ea:80:e8:ba: + 7e:d6:34:eb:fc:88:f1:16:42:b2:bb:22:9c:e0:36:84:23:f5: + 20:86:dc:38:55:89:dc:0e:67:7c:c7:bb:2f:36:25:bc:ca:be: + 2b:1c:79:26:79:2b:49:17:3c:76:02:cf:f9:e3:8a:3f:15:69: + 2c:12:5c:99:93:85:11:c8:90:68:d6:f1:8d:87:30:bf:0d:ec: + 89:9a:f4:48:cc:26:95:c7:65:cd:30:cc:d0:93:c3:80:3f:ad: + a6:fa:7c:88:82:53:0e:9b:16:c3:dd:27:9a:d0:99:05:fb:2d: + d0:e6:fa:08:92:46:ee:dd:44:9d:56:b2:95:52:99:db:5a:20: + 16:c9:a7:a3:0b:a3:c5:d8:0a:b7:c2:cf:f7:95:a4:df:4c:f9: + 2f:69:a0:27:6e:0f:85:3e:76:b4:3d:6b:f7:4a:de:1a:de:a4: + d3:01:91:f1:44:59:44:2c:93:15:52:99:da:6e:93:b8:da:54: + b5:06:ff:82:9b:cf:57:0c:7d:06:6b:ff:ce:b9:c9:47:62:c9: + 15:f4:67:4e:57:12:74:d7:b5:31:53:cc:eb:d7:05:4d:34:58: + a9:5d:33:85:2d:72:6f:12:99:7e:60:63:27:05:74:8b:85:0c: + 0b:f9:b3:b4:e7:f6:4e:4b +-----BEGIN CERTIFICATE----- +MIIFBzCCAu+gAwIBAgIBCTANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMCAXDTE5MDMyMjIyMjUxMFoYDzI1 +MTgxMTIxMjIyNTEwWjAnMQswCQYDVQQGEwJTRTEYMBYGA1UEAwwPd3d3LnRlc3Qu +aDVsLnNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAu8qFnD1rWiEb +LIQ1SDe8E2KT/3u+SUDiNrV6VKTjD7GHKd5rfYbstiXFnNwTBldMgBuG8KzmZI+q +Y8woSVyECbgPMZndNtJCtarfMfYnysJMUBFbAZQX2ipcIeW1gSNpPk8dCEiVVzB3 +lq6beIcQ5G2Q6HitGUE9uJEctgR4UuXkPyjfARPaqsskz/WT+QK4xdxH+3nl3p4Z +syirLb1zSA9xCraBWm0CbZzIwxTVgr8ZuNBvWDJsdpHzB2slSln0LcmN2u7MMFtb +2PMNYyiNnN8htTpB4FXQX/EyRQtrQLbYQwx7KD0tfEAZouDWogsyZaOB6RzlavZh +fGb6xhC/XR3ZwRpn+6BDFf/1QFoMiktIONXHd0gZ9yHecxeXzwPXw4QiOK7yvtJh +rzc4MUEBl1iTuoDauwAzqCuYNICLAB6DAsQmP1xRqSnjrLE2MVeHQ5RXOhf0bTS/ +I7aiVtK3cn41NNlYRsFkLT/n/+T9QhHZBJi6nYjs5667EUL9AMskFyeULKA03xiL +erw5VWwCO0TPpELz44Fb1pCOeNc/TO9s3k1+Qc6Hj8A4pFcFYzKFw96IqowLBN/D +hmRMGZHh5LL49vP+k8M+wbF0tHL/iJSNNKOwnVWq/ry8QVVJivHu3foOofq5cafV +/Lf8q8Kvj71uSOxU8PiotNdsEQ75FqsCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNV +HQ8EBAMCBeAwHQYDVR0OBBYEFKo8DZXNFAqcpS0Jbu5bQ6mvP25UMA0GCSqGSIb3 +DQEBBQUAA4ICAQCj7AYbZrPLoxI47zDcpqH801LQc8ipTQuOAioIpk9VQS9GK8/p +BAedQkcNiGQfOa7XmzBDR/m6lqgvem5LIpxlx5yMxtLyX6n93uueehO4IgxZFZC6 +ZbcIPd0u4gm+R1MlCozT4HjpGhWOMrJfduFoPC8zPzgX/zutQ7cOhwiXa42nbDve +Ghg9W3QLhwOKSbAihCpy8QHDtVWeSlbBlmy6nOtYzk5T/biZAsHVYu+1RHMcxk8m ++Y1r6Vi+PEpW72Vq9XEcO470rkNEqyaAQdqpa5tjSbw5djse/qUkDkxZUZ1HxM4r +kGXo+K6rqhTM0krPhSBA3YBJ6nyYBO5XQea8E/woXghc7vobcuqA6Lp+1jTr/Ijx +FkKyuyKc4DaEI/Ughtw4VYncDmd8x7svNiW8yr4rHHkmeStJFzx2As/544o/FWks +ElyZk4URyJBo1vGNhzC/DeyJmvRIzCaVx2XNMMzQk8OAP62m+nyIglMOmxbD3Sea +0JkF+y3Q5voIkkbu3USdVrKVUpnbWiAWyaejC6PF2Aq3ws/3laTfTPkvaaAnbg+F +Pna0PWv3St4a3qTTAZHxRFlELJMVUpnabpO42lS1Bv+Cm89XDH0Ga//OuclHYskV +9GdOVxJ017UxU8zr1wVNNFipXTOFLXJvEpl+YGMnBXSLhQwL+bO05/ZOSw== +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/https.key b/third_party/heimdal/lib/hx509/data/https.key new file mode 100644 index 0000000..59d7bfd --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/https.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +PJKGZjLpgXkldTcRw00N0NRePp73WR86 +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/j.pem b/third_party/heimdal/lib/hx509/data/j.pem new file mode 100644 index 0000000..45ae8e8 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/j.pem @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEajCCA1KgAwIBAgIBATANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJKUDEN +MAsGA1UECgwESlBLSTEpMCcGA1UECwwgUHJlZmVjdHVyYWwgQXNzb2NpYXRpb24g +Rm9yIEpQS0kxETAPBgNVBAsMCEJyaWRnZUNBMB4XDTAzMTIyNzA1MDgxNVoXDTEz +MTIyNjE0NTk1OVowWjELMAkGA1UEBhMCSlAxDTALBgNVBAoMBEpQS0kxKTAnBgNV +BAsMIFByZWZlY3R1cmFsIEFzc29jaWF0aW9uIEZvciBKUEtJMREwDwYDVQQLDAhC +cmlkZ2VDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANTnUmg7K3m8 +52vd77kwkq156euwoWm5no8E8kmaTSc7x2RABPpqNTlMKdZ6ttsyYrqREeDkcvPL +yF7yf/I8+innasNtsytcTAy8xY8Avsbd4JkCGW9dyPjk9pzzc3yLQ64Rx2fujRn2 +agcEVdPCr/XpJygX8FD5bbhkZ0CVoiASBmlHOcC3YpFlfbT1QcpOSOb7o+VdKVEi +MMfbBuU2IlYIaSr/R1nO7RPNtkqkFWJ1/nKjKHyzZje7j70qSxb+BTGcNgTHa1YA +UrogKB+UpBftmb4ds+XlkEJ1dvwokiSbCDaWFKD+YD4B2s0bvjCbw8xuZFYGhNyR +/2D5XfN1s2MCAwEAAaOCATkwggE1MA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MG0GA1UdHwRmMGQwYqBgoF6kXDBaMQswCQYDVQQGEwJKUDENMAsGA1UE +CgwESlBLSTEpMCcGA1UECwwgUHJlZmVjdHVyYWwgQXNzb2NpYXRpb24gRm9yIEpQ +S0kxETAPBgNVBAsMCEJyaWRnZUNBMIGDBgNVHREEfDB6pHgwdjELMAkGA1UEBhMC +SlAxJzAlBgNVBAoMHuWFrOeahOWAi+S6uuiqjeiovOOCteODvOODk+OCuTEeMBwG +A1UECwwV6YO96YGT5bqc55yM5Y2U6K2w5LyaMR4wHAYDVQQLDBXjg5bjg6rjg4Pj +grjoqo3oqLzlsYAwHQYDVR0OBBYEFNQXMiCqQNkR2OaZmQgLtf8mR8p8MA0GCSqG +SIb3DQEBBQUAA4IBAQATjJo4reTNPC5CsvAKu1RYT8PyXFVYHbKsEpGt4GR8pDCg +HEGAiAhHSNrGh9CagZMXADvlG0gmMOnXowriQQixrtpkmx0TB8tNAlZptZWkZC+R +8TnjOkHrk2nFAEC3ezbdK0R7MR4tJLDQCnhEWbg50rf0wZ/aF8uAaVeEtHXa6W0M +Xq3dSe0XAcrLbX4zZHQTaWvdpLAIjl6DZ3SCieRMyoWUL+LXaLFdTP5WBCd+No58 +IounD9X4xxze2aeRVaiV/WnQ0OSPNS7n7YXy6xQdnaOU4KRW/Lne1EDf5IfWC/ih +bVAmhZMbcrkWWcsR6aCPG+2mV3zTD6AUzuKPal8Y +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/kdc.crt b/third_party/heimdal/lib/hx509/data/kdc.crt new file mode 100644 index 0000000..a92fcc0 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/kdc.crt @@ -0,0 +1,122 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 8 (0x8) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Mar 22 22:25:09 2019 GMT + Not After : Nov 21 22:25:09 2518 GMT + Subject: C=SE, CN=kdc + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:d1:73:ec:58:67:7a:65:30:ab:19:15:a1:bf:1e: + de:db:e5:4a:92:f0:99:8a:eb:02:6d:e4:31:1a:c7: + 4d:07:57:b1:82:9e:d2:d2:c7:f3:0b:b2:82:61:5c: + ba:38:c3:54:e9:e1:be:6b:5f:0d:22:62:2b:cb:d5: + 34:0e:63:0b:50:8a:8b:b3:be:6a:e1:85:dc:b1:28: + 13:ee:dd:6e:40:d5:48:1d:eb:aa:04:0b:e7:c8:1c: + 6d:60:54:b6:cc:be:52:5a:88:22:ce:07:2d:3f:cb: + fc:00:ab:8b:a5:e7:32:8e:b1:8b:03:d8:81:a2:69: + d4:9f:3a:ff:da:b5:e3:0d:e3:21:54:29:cb:61:ba: + 16:13:94:97:1b:72:24:6d:da:d7:d9:35:b1:57:f1: + 3b:9d:ee:90:76:4e:58:1f:4e:76:12:c6:89:2a:54: + bf:e8:53:5a:de:05:79:93:0b:41:2c:03:c5:30:58: + a8:e6:57:08:f9:47:7c:c0:3a:5c:eb:1b:33:68:52: + 02:19:08:e6:35:48:05:a7:51:22:89:1c:1e:c8:0b: + 55:73:b2:c9:75:f9:74:aa:de:5e:3a:54:f8:96:47: + cf:25:2d:75:e7:71:74:31:91:17:85:44:89:8a:16: + 88:ca:12:dd:0e:36:4d:e5:af:b3:db:d3:7c:53:8d: + 7a:08:69:92:72:81:c8:13:c7:71:96:8f:2d:54:98: + c9:63:10:26:be:59:8f:db:82:47:c1:29:c6:28:7f: + a0:16:bf:85:a2:eb:2f:2f:46:86:6b:77:1f:31:30: + d4:52:35:32:09:16:cd:48:ec:3c:4c:2c:03:e5:b9: + 90:e9:f7:b4:7d:97:91:31:27:4e:df:b6:bd:b6:ec: + ca:47:16:00:58:e9:87:4f:20:af:ef:4c:34:42:5b: + 3e:28:aa:cd:39:75:3b:6f:7c:b9:7b:50:76:67:25: + 31:46:f5:34:aa:c6:5a:22:77:b5:9d:6d:88:4d:f1: + e6:e7:ca:d2:d8:70:10:58:39:58:0f:ce:8d:b3:4d: + e4:f4:80:ca:31:75:3c:38:61:6c:d9:17:d2:aa:72: + f9:e0:ac:86:ab:33:16:84:e8:c8:de:58:9d:78:ac: + f1:2a:64:b8:e3:f2:cb:20:42:dd:f9:bd:2e:c2:84: + 6e:11:34:76:a5:c5:54:c5:51:9b:cb:85:d1:05:82: + 1c:33:d5:95:18:ad:4c:94:d2:7b:4f:72:23:ff:c1: + 4b:a2:ea:1a:3a:18:c2:f5:c8:08:76:00:12:25:e5: + ee:30:b9:8d:2f:0f:95:3d:70:ac:6a:eb:d8:c5:71: + 9a:cf:a9:a6:6a:ce:45:07:a4:41:de:85:fb:ad:e0: + 39:0b:6f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Extended Key Usage: + Signing KDC Response + X509v3 Subject Key Identifier: + 62:AF:D5:17:E4:9F:2A:8D:8A:CA:2B:05:E1:25:66:BB:61:03:77:EA + X509v3 Subject Alternative Name: + othername:<unsupported> + Signature Algorithm: sha1WithRSAEncryption + 41:29:9f:70:6b:36:28:cc:86:e1:4d:ae:25:34:b1:24:ab:f8: + 03:de:28:da:d1:13:8e:03:d3:5a:57:72:69:f9:04:1c:e0:1d: + 14:91:c7:a0:8b:ab:c7:61:6e:4e:86:2a:2a:40:22:10:10:58: + 0c:18:95:eb:d2:15:18:35:3c:fc:42:25:1a:dc:03:cb:ba:f3: + 81:80:d2:45:4e:c6:90:11:2f:e9:db:76:9a:e3:1d:0c:04:dc: + fb:d9:ec:bd:48:38:66:78:d6:52:c2:bc:ae:20:9b:1d:87:28: + 9f:38:fa:db:8f:17:1f:3e:29:85:17:a0:95:bd:72:88:0c:93: + 88:ba:8e:31:67:2b:03:b0:bf:3a:7e:e4:e2:82:f7:6c:36:1a: + d1:8e:7c:87:63:17:e4:68:7f:4b:e7:dc:40:b5:02:5a:62:be: + 54:ee:11:30:39:80:2a:c0:3e:8f:3b:67:cb:9d:9f:ee:c1:ea: + f1:4c:e8:55:24:6a:73:84:ef:82:ca:99:ec:84:05:5e:82:a1: + 52:40:5e:71:10:c9:c3:9b:18:ce:7f:50:db:8a:49:d4:b6:b9: + 5e:ef:13:4c:e8:be:76:2b:cc:f9:eb:9e:9b:4b:29:8e:ee:1c: + e5:bd:08:f0:50:63:e2:c3:94:20:2f:fe:cb:6a:ed:2b:2a:e2: + 51:44:3d:06:d1:b4:43:26:43:07:4d:c9:e1:4f:9d:3d:0f:a6: + 74:93:ff:51:74:c8:aa:2d:76:ab:93:6f:84:47:2d:70:37:d2: + 21:f0:cb:4d:a5:8b:df:91:4b:95:f0:ba:fe:d9:fc:f2:ed:b5: + e7:91:03:5a:ad:12:43:f3:ba:c8:a7:51:34:9b:40:bd:71:39: + af:b1:9f:e4:9f:3f:1b:27:a5:84:43:a2:c3:3f:52:63:a8:bf: + 8b:59:82:53:b5:26:64:16:73:90:f8:7b:7d:ce:f6:41:b6:8b: + 81:56:90:c2:ff:46:46:8f:63:3d:95:d9:f0:49:73:37:d9:14: + 2b:26:95:ac:19:29:1d:cb:c2:03:d7:36:4e:4a:39:3e:51:02: + de:aa:dc:6b:77:a8:57:ba:50:21:0e:8e:b7:48:bc:44:fa:45: + db:c9:bb:72:ea:e4:2a:7a:35:75:3c:68:29:5d:b9:57:0b:d3: + 2e:2c:4f:01:1b:f0:21:0c:fc:95:17:b7:40:be:aa:0c:f9:04: + 60:6a:d1:54:0d:b9:68:d7:e9:7a:f4:96:ad:f1:a0:15:15:c2: + 51:61:44:5f:0e:bb:98:d1:81:9f:c1:81:d6:e2:26:d5:11:56: + d2:cd:0f:9c:6b:69:f0:78:24:ff:bf:df:02:2b:0d:d1:83:5b: + 14:4d:c0:e2:80:47:65:2b +-----BEGIN CERTIFICATE----- +MIIFWzCCA0OgAwIBAgIBCDANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMCAXDTE5MDMyMjIyMjUwOVoYDzI1 +MTgxMTIxMjIyNTA5WjAbMQswCQYDVQQGEwJTRTEMMAoGA1UEAwwDa2RjMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0XPsWGd6ZTCrGRWhvx7e2+VKkvCZ +iusCbeQxGsdNB1exgp7S0sfzC7KCYVy6OMNU6eG+a18NImIry9U0DmMLUIqLs75q +4YXcsSgT7t1uQNVIHeuqBAvnyBxtYFS2zL5SWogizgctP8v8AKuLpecyjrGLA9iB +omnUnzr/2rXjDeMhVCnLYboWE5SXG3IkbdrX2TWxV/E7ne6Qdk5YH052EsaJKlS/ +6FNa3gV5kwtBLAPFMFio5lcI+Ud8wDpc6xszaFICGQjmNUgFp1EiiRweyAtVc7LJ +dfl0qt5eOlT4lkfPJS1153F0MZEXhUSJihaIyhLdDjZN5a+z29N8U416CGmScoHI +E8dxlo8tVJjJYxAmvlmP24JHwSnGKH+gFr+FousvL0aGa3cfMTDUUjUyCRbNSOw8 +TCwD5bmQ6fe0fZeRMSdO37a9tuzKRxYAWOmHTyCv70w0Qls+KKrNOXU7b3y5e1B2 +ZyUxRvU0qsZaIne1nW2ITfHm58rS2HAQWDlYD86Ns03k9IDKMXU8OGFs2RfSqnL5 +4KyGqzMWhOjI3lideKzxKmS44/LLIELd+b0uwoRuETR2pcVUxVGby4XRBYIcM9WV +GK1MlNJ7T3Ij/8FLouoaOhjC9cgIdgASJeXuMLmNLw+VPXCsauvYxXGaz6mmas5F +B6RB3oX7reA5C28CAwEAAaOBmDCBlTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAS +BgNVHSUECzAJBgcrBgEFAgMFMB0GA1UdDgQWBBRir9UX5J8qjYrKKwXhJWa7YQN3 +6jBIBgNVHREEQTA/oD0GBisGAQUCAqAzMDGgDRsLVEVTVC5INUwuU0WhIDAeoAMC +AQGhFzAVGwZrcmJ0Z3QbC1RFU1QuSDVMLlNFMA0GCSqGSIb3DQEBBQUAA4ICAQBB +KZ9wazYozIbhTa4lNLEkq/gD3ija0ROOA9NaV3Jp+QQc4B0Ukcegi6vHYW5Ohioq +QCIQEFgMGJXr0hUYNTz8QiUa3APLuvOBgNJFTsaQES/p23aa4x0MBNz72ey9SDhm +eNZSwryuIJsdhyifOPrbjxcfPimFF6CVvXKIDJOIuo4xZysDsL86fuTigvdsNhrR +jnyHYxfkaH9L59xAtQJaYr5U7hEwOYAqwD6PO2fLnZ/uwerxTOhVJGpzhO+Cypns +hAVegqFSQF5xEMnDmxjOf1DbiknUtrle7xNM6L52K8z5656bSymO7hzlvQjwUGPi +w5QgL/7Lau0rKuJRRD0G0bRDJkMHTcnhT509D6Z0k/9RdMiqLXark2+ERy1wN9Ih +8MtNpYvfkUuV8Lr+2fzy7bXnkQNarRJD87rIp1E0m0C9cTmvsZ/knz8bJ6WEQ6LD +P1JjqL+LWYJTtSZkFnOQ+Ht9zvZBtouBVpDC/0ZGj2M9ldnwSXM32RQrJpWsGSkd +y8ID1zZOSjk+UQLeqtxrd6hXulAhDo63SLxE+kXbybty6uQqejV1PGgpXblXC9Mu +LE8BG/AhDPyVF7dAvqoM+QRgatFUDblo1+l69Jat8aAVFcJRYURfDruY0YGfwYHW +4ibVEVbSzQ+ca2nweCT/v98CKw3Rg1sUTcDigEdlKw== +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/kdc.key b/third_party/heimdal/lib/hx509/data/kdc.key new file mode 100644 index 0000000..1984f20 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/kdc.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +RCBsiAswkZ1vTsDII1BKYPknuvgH9g== +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/key.der b/third_party/heimdal/lib/hx509/data/key.der Binary files differnew file mode 100644 index 0000000..e7c665e --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/key.der diff --git a/third_party/heimdal/lib/hx509/data/key2.der b/third_party/heimdal/lib/hx509/data/key2.der Binary files differnew file mode 100644 index 0000000..fe3f413 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/key2.der diff --git a/third_party/heimdal/lib/hx509/data/mkcert.sh b/third_party/heimdal/lib/hx509/data/mkcert.sh new file mode 100755 index 0000000..c06528d --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/mkcert.sh @@ -0,0 +1,83 @@ +#! /bin/bash + +set -e + +DAYS=182500 + +key() { + local key=$1; shift + + if [ ! -f "${key}.pem" ]; then + openssl genpkey \ + -paramfile <(openssl ecparam -name prime256v1) \ + -out "${key}.pem" + fi +} + +req() { + local key=$1; shift + local dn=$1; shift + + openssl req -new -sha256 -key "${key}.pem" \ + -config <(printf "[req]\n%s\n%s\n[dn]\nCN_default=foo\n" \ + "prompt = yes" "distinguished_name = dn") \ + -subj "${dn}" +} + +cert() { + local cert=$1; shift + local exts=$1; shift + + openssl x509 -req -sha256 -out "${cert}.pem" \ + -extfile <(printf "%s\n" "$exts") "$@" +} + +genroot() { + local dn=$1; shift + local key=$1; shift + local cert=$1; shift + + exts=$(printf "%s\n%s\n%s\n%s\n" \ + "subjectKeyIdentifier = hash" \ + "authorityKeyIdentifier = keyid" \ + "basicConstraints = CA:true" \ + "keyUsage = keyCertSign, cRLSign" ) + key "$key"; req "$key" "$dn" | + cert "$cert" "$exts" -signkey "${key}.pem" \ + -set_serial 1 -days "${DAYS}" +} + +genee() { + local dn=$1; shift + local key=$1; shift + local cert=$1; shift + local cakey=$1; shift + local cacert=$1; shift + + exts=$(printf "%s\n%s\n%s\n%s\n" \ + "subjectKeyIdentifier = hash" \ + "authorityKeyIdentifier = keyid, issuer" \ + "basicConstraints = CA:false" \ + "keyUsage = digitalSignature, keyEncipherment, dataEncipherment" \ + ) + key "$key"; req "$key" "$dn" | + cert "$cert" "$exts" -CA "${cacert}.pem" -CAkey "${cakey}.pem" \ + -set_serial 2 -days "${DAYS}" "$@" +} + + +genroot "/C=SE/O=Heimdal/CN=CA secp256r1" \ + secp256r1TestCA.key secp256r1TestCA.cert +genee "/C=SE/O=Heimdal/CN=Server" \ + secp256r2TestServer.key secp256r2TestServer.cert \ + secp256r1TestCA.key secp256r1TestCA.cert +genee "/C=SE/O=Heimdal/CN=Client" \ + secp256r2TestClient.key secp256r2TestClient.cert \ + secp256r1TestCA.key secp256r1TestCA.cert + +cat secp256r1TestCA.key.pem secp256r1TestCA.cert.pem > \ + secp256r1TestCA.pem +cat secp256r2TestClient.cert.pem secp256r2TestClient.key.pem > \ + secp256r2TestClient.pem +cat secp256r2TestServer.cert.pem secp256r2TestServer.key.pem > \ + secp256r2TestServer.pem diff --git a/third_party/heimdal/lib/hx509/data/n0ll.pem b/third_party/heimdal/lib/hx509/data/n0ll.pem new file mode 100644 index 0000000..4b17377 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/n0ll.pem @@ -0,0 +1,47 @@ +https://www.noisebridge.net/pipermail/noisebridge-discuss/2009-September/008400.html + +Jacob Appelbaum jacob at appelbaum.net +Tue Sep 29 22:51:33 PDT 2009 + + +I hope this release will help with confirmation of the bug and with +regression testing. Feel free to use this certificate for anything +relating to free software too. Consider it released into the public +domain of interesting integers. + +-----BEGIN CERTIFICATE----- +MIIGTjCCBbegAwIBAgIDExefMA0GCSqGSIb3DQEBBQUAMIIBEjELMAkGA1UEBhMC +RVMxEjAQBgNVBAgTCUJhcmNlbG9uYTESMBAGA1UEBxMJQmFyY2Vsb25hMSkwJwYD +VQQKEyBJUFMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgcy5sLjEuMCwGA1UEChQl +Z2VuZXJhbEBpcHNjYS5jb20gQy5JLkYuICBCLUI2MjIxMDY5NTEuMCwGA1UECxMl +aXBzQ0EgQ0xBU0VBMSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMl +aXBzQ0EgQ0xBU0VBMSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEgMB4GCSqGSIb3 +DQEJARYRZ2VuZXJhbEBpcHNjYS5jb20wHhcNMDkwNzMwMDcxNDQyWhcNMTEwNzMw +MDcxNDQyWjCBnjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAU +BgNVBAcTDVNhbiBGcmFuY2lzY28xFDASBgNVBAoTC05vaXNlYnJpZGdlMSMwIQYD +VQQLExpNb3hpZSBNYXJsaW5zcGlrZSBGYW4gQ2x1YjEnMCUGA1UEAxQeKgB0aG91 +Z2h0Y3JpbWUubm9pc2VicmlkZ2UubmV0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB +iQKBgQDPTRdCAI0MQZUxjEAwvF5CtigJdS8ZYdmrTezzRMQcAZVvJ+twB5hPHgXQ +82xJRebeSHpZ8MKTajecAnJPvRQ2JqFwl9T+SyTozSkeYRqFsG+WBoMQE9aJn70H +Z/FC3ptjZ4uW+QbvfJNLavk5MTJ/mFnvzpG+Bc7wgjPYdgZMnwIDAQABo4IDITCC +Ax0wCQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwCwYDVR0PBAQDAgP4MBMG +A1UdJQQMMAoGCCsGAQUFBwMBMB0GA1UdDgQWBBStfpIwBXE+eXWUWtE3s5JqXon2 +TzAfBgNVHSMEGDAWgBQOB2DUOckbW12QeyPI0jSdSppGOTAJBgNVHREEAjAAMBwG +A1UdEgQVMBOBEWdlbmVyYWxAaXBzY2EuY29tMHIGCWCGSAGG+EIBDQRlFmNPcmdh +bml6YXRpb24gSW5mb3JtYXRpb24gTk9UIFZBTElEQVRFRC4gQ0xBU0VBMSBTZXJ2 +ZXIgQ2VydGlmaWNhdGUgaXNzdWVkIGJ5IGh0dHBzOi8vd3d3Lmlwc2NhLmNvbS8w +LwYJYIZIAYb4QgECBCIWIGh0dHBzOi8vd3d3Lmlwc2NhLmNvbS9pcHNjYTIwMDIv +MEMGCWCGSAGG+EIBBAQ2FjRodHRwczovL3d3dy5pcHNjYS5jb20vaXBzY2EyMDAy +L2lwc2NhMjAwMkNMQVNFQTEuY3JsMEYGCWCGSAGG+EIBAwQ5FjdodHRwczovL3d3 +dy5pcHNjYS5jb20vaXBzY2EyMDAyL3Jldm9jYXRpb25DTEFTRUExLmh0bWw/MEMG +CWCGSAGG+EIBBwQ2FjRodHRwczovL3d3dy5pcHNjYS5jb20vaXBzY2EyMDAyL3Jl +bmV3YWxDTEFTRUExLmh0bWw/MEEGCWCGSAGG+EIBCAQ0FjJodHRwczovL3d3dy5p +cHNjYS5jb20vaXBzY2EyMDAyL3BvbGljeUNMQVNFQTEuaHRtbDCBgwYDVR0fBHww +ejA5oDegNYYzaHR0cDovL3d3dy5pcHNjYS5jb20vaXBzY2EyMDAyL2lwc2NhMjAw +MkNMQVNFQTEuY3JsMD2gO6A5hjdodHRwOi8vd3d3YmFjay5pcHNjYS5jb20vaXBz +Y2EyMDAyL2lwc2NhMjAwMkNMQVNFQTEuY3JsMDIGCCsGAQUFBwEBBCYwJDAiBggr +BgEFBQcwAYYWaHR0cDovL29jc3AuaXBzY2EuY29tLzANBgkqhkiG9w0BAQUFAAOB +gQAjzXaLBu+/+RP0vQ6WjW/Pxgm4WQYhecqZ2+7ZFbsUCMJPQ8XE2uv+rIteGnRF +Zr3hYb+dVlfUnethjPhazZW+/hU4FePqmlbTtmMe+zMLThiScyC8y3EW4L4BZYcp +p1drPlZIj2RmSgPQ99oToUk5O6t+LMg1N14ajr9TpM8yNQ== +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/nist-data b/third_party/heimdal/lib/hx509/data/nist-data new file mode 100644 index 0000000..7407b80 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/nist-data @@ -0,0 +1,91 @@ +# $Id$ +# id verify cert hxtool-verify-arguments... +# p(ass) f(ail) +# Those id's that end with i are invariants of the orignal test +# +# 4.1 Signature Verification +# +4.1.1 p ValidCertificatePathTest1EE.crt GoodCACert.crt GoodCACRL.crl +4.1.2 f InvalidCASignatureTest2EE.crt BadSignedCACert.crt BadSignedCACRL.crl +4.1.3 f InvalidEESignatureTest3EE.crt GoodCACert.crt GoodCACRL.crl +#4.1.4 p ValidDSASignaturesTest4EE.crt DSACACert.crt DSACACRL.crl +#4.1.5 p ValidDSAParameterInheritanceTest5EE.crl DSAParametersInheritedCACert.crt DSAParametersInheritedCACRL.crl DSACACert.crt DSACACRL.crl +#4.1.6 f InvalidDSASignaturesTest6EE.crt DSACACert.crt DSACACRL.crl +# +# 4.2 Validity Periods +# +4.2.1 f InvalidCAnotBeforeDateTest1EE.crt BadnotBeforeDateCACert.crt BadnotBeforeDateCACRL.crl +4.2.2 f InvalidEEnotBeforeDateTest2EE.crt GoodCACert.crt GoodCACRL.crl +4.2.3 p Validpre2000UTCnotBeforeDateTest3EE.crt GoodCACert.crt GoodCACRL.crl +4.2.4 p ValidGeneralizedTimenotBeforeDateTest4EE.crt GoodCACert.crt GoodCACRL.crl +4.2.5 f InvalidCAnotAfterDateTest5EE.crt BadnotAfterDateCACert.crt BadnotAfterDateCACRL.crl +4.2.6 f InvalidEEnotAfterDateTest6EE.crt GoodCACert.crt GoodCACRL.crl +4.2.7 f Invalidpre2000UTCEEnotAfterDateTest7EE.crt GoodCACert.crt GoodCACRL.crl +#4.2.8 p ValidGeneralizedTimenotAfterDateTest8EE.crt GoodCACert.crt GoodCACRL.crl +# +# 4.4 CRtests +# +4.4.1 f InvalidMissingCRLTest1EE.crt NoCRLCACert.crt +4.4.1i p InvalidMissingCRLTest1EE.crt --missing-revoke NoCRLCACert.crt +4.4.2 f InvalidRevokedEETest3EE.crt GoodCACert.crt InvalidRevokedCATest2EE.crt GoodCACRL.crl RevokedsubCACRL.crl +4.4.2i p InvalidRevokedEETest3EE.crt --missing-revoke GoodCACert.crt InvalidRevokedCATest2EE.crt +4.4.3 f InvalidRevokedEETest3EE.crt GoodCACert.crt GoodCACRL.crl +4.4.3i p InvalidRevokedEETest3EE.crt --missing-revoke GoodCACert.crt +4.4.4 f InvalidBadCRLSignatureTest4EE.crt BadCRLSignatureCACert.crt BadCRLSignatureCACRL.crl +4.4.4i p InvalidBadCRLSignatureTest4EE.crt --missing-revoke BadCRLSignatureCACert.crt +4.4.5 f InvalidBadCRLIssuerNameTest5EE.crt BadCRLIssuerNameCACert.crt BadCRLIssuerNameCACRL.crl +4.4.5i p InvalidBadCRLIssuerNameTest5EE.crt --missing-revoke BadCRLIssuerNameCACert.crt +4.4.6 f InvalidWrongCRLTest6EE.crt WrongCRLCACert.crt WrongCRLCACRL.crl +4.4.7 p ValidTwoCRLsTest7EE.crt TwoCRLsCACert.crt TwoCRLsCAGoodCRL.crl TwoCRLsCABadCRL.crl +4.4.8 f InvalidUnknownCRLEntryExtensionTest8EE.crt UnknownCRLEntryExtensionCACert.crt UnknownCRLEntryExtensionCACRL.crl +4.4.9 f InvalidUnknownCRLExtensionTest9EE.crt UnknownCRLExtensionCACert.crt UnknownCRLExtensionCACRL.crl +4.4.10 f InvalidUnknownCRLExtensionTest10EE.crt UnknownCRLExtensionCACert.crt UnknownCRLExtensionCACRL.crl +4.4.11 f InvalidOldCRLnextUpdateTest11EE.crt OldCRLnextUpdateCACert.crt OldCRLnextUpdateCACRL.crl +4.4.12 f Invalidpre2000CRLnextUpdateTest12EE.crt pre2000CRLnextUpdateCACert.crt pre2000CRLnextUpdateCACRL.crl +#4.4.13-xxx s ValidGeneralizedTimeCRLnextUpdateTest13EE.crt GeneralizedTimeCRLnextUpdateCACert.crt GeneralizedTimeCRLnextUpdateCACRL.crl +4.4.14 p ValidNegativeSerialNumberTest14EE.crt NegativeSerialNumberCACert.crt NegativeSerialNumberCACRL.crl +4.4.15 f InvalidNegativeSerialNumberTest15EE.crt NegativeSerialNumberCACert.crt NegativeSerialNumberCACRL.crl +4.4.16 p ValidLongSerialNumberTest16EE.crt LongSerialNumberCACert.crt LongSerialNumberCACRL.crl +4.4.17 p ValidLongSerialNumberTest17EE.crt LongSerialNumberCACert.crt LongSerialNumberCACRL.crl +4.4.18 f InvalidLongSerialNumberTest18EE.crt LongSerialNumberCACert.crt LongSerialNumberCACRL.crl +# +# +# 4.8 Ceificate Policies +incomplete4.8.2 p AllCertificatesNoPoliciesTest2EE.crt NoPoliciesCACert.crt NoPoliciesCACRL.crl +incomplete4.8.10 p AllCertificatesSamePoliciesTest10EE.crt PoliciesP12CACert.crt PoliciesP12CACRL.crl +incomplete4.8.13 p AllCertificatesSamePoliciesTest13EE.crt PoliciesP123CACert.crt PoliciesP123CACRL.crl +incomplete4.8.11 p AllCertificatesanyPolicyTest11EE.crt anyPolicyCACert.crt anyPolicyCACRL.crl +unknown p AnyPolicyTest14EE.crt anyPolicyCACert.crt anyPolicyCACRL.crl +unknown f BadSignedCACert.crt +unknown f BadnotAfterDateCACert.crt +unknown f BadnotBeforeDateCACert.crt +# +# 4.13 Name Constraints +# +4.13.1 p ValidDNnameConstraintsTest1EE.crt nameConstraintsDN1CACert.crt nameConstraintsDN1CACRL.crl +4.13.2 f InvalidDNnameConstraintsTest2EE.crt nameConstraintsDN1CACert.crt nameConstraintsDN1CACRL.crl +4.13.3 f InvalidDNnameConstraintsTest3EE.crt nameConstraintsDN1CACert.crt nameConstraintsDN1CACRL.crl +4.13.4 p ValidDNnameConstraintsTest4EE.crt nameConstraintsDN1CACert.crt nameConstraintsDN1CACRL.crl +4.13.5 p ValidDNnameConstraintsTest5EE.crt nameConstraintsDN2CACert.crt nameConstraintsDN2CACRL.crl +4.13.6 p ValidDNnameConstraintsTest6EE.crt nameConstraintsDN3CACert.crt nameConstraintsDN3CACRL.crl +4.13.7 f InvalidDNnameConstraintsTest7EE.crt nameConstraintsDN3CACert.crt nameConstraintsDN3CACRL.crl +4.13.8 f InvalidDNnameConstraintsTest8EE.crt nameConstraintsDN4CACert.crt nameConstraintsDN4CACRL.crl +4.13.9 f InvalidDNnameConstraintsTest9EE.crt nameConstraintsDN4CACert.crt nameConstraintsDN4CACRL.crl +4.13.10 f InvalidDNnameConstraintsTest10EE.crt nameConstraintsDN5CACert.crt nameConstraintsDN5CACRL.crl +4.13.11 p ValidDNnameConstraintsTest11EE.crt nameConstraintsDN5CACert.crt nameConstraintsDN5CACRL.crl +4.13.12 f InvalidDNnameConstraintsTest12EE.crt nameConstraintsDN1subCA1Cert.crt nameConstraintsDN1subCA1CRL.crl nameConstraintsDN1CACert.crt nameConstraintsDN1CACRL.crl +4.13.13 f InvalidDNnameConstraintsTest13EE.crt nameConstraintsDN1subCA1Cert.crt nameConstraintsDN1subCA1CRL.crl nameConstraintsDN1CACert.crt nameConstraintsDN1CACRL.crl +4.13.14 p ValidDNnameConstraintsTest14EE.crt nameConstraintsDN1subCA2Cert.crt nameConstraintsDN1subCA2CRL.crl nameConstraintsDN1CACert.crt nameConstraintsDN1CACRL.crl +4.13.15 f InvalidDNnameConstraintsTest15EE.crt nameConstraintsDN3subCA1Cert.crt nameConstraintsDN3subCA1CRL.crl nameConstraintsDN3CACert.crt nameConstraintsDN3CACRL.crl +4.13.16 f InvalidDNnameConstraintsTest16EE.crt nameConstraintsDN3subCA1Cert.crt nameConstraintsDN3subCA1CRL.crl nameConstraintsDN3CACert.crt nameConstraintsDN3CACRL.crl +4.13.17 f InvalidDNnameConstraintsTest17EE.crt nameConstraintsDN3subCA2Cert.crt nameConstraintsDN3subCA2CRL.crl nameConstraintsDN3CACert.crt nameConstraintsDN3CACRL.crl +4.13.18 p ValidDNnameConstraintsTest18EE.crt nameConstraintsDN3subCA2Cert.crt nameConstraintsDN3subCA2CRL.crl nameConstraintsDN3CACert.crt nameConstraintsDN3CACRL.crl +# +# no crl for self issued cert +# +#4.13.19 p ValidDNnameConstraintsTest19EE.crt nameConstraintsDN1SelfIssuedCACert.crt nameConstraintsDN1CACert.crt nameConstraintsDN1CACRL.crl +# ?? +4.13.20 f InvalidDNnameConstraintsTest20EE.crt nameConstraintsDN1CACert.crt nameConstraintsDN1CACRL.crl +#4.13.21 p ValidRFC822nameConstraintsTest21EE.crt nameConstraintsRFC822CA1Cert.crt nameConstraintsRFC822CA1CRL.crl +#page 74 +end diff --git a/third_party/heimdal/lib/hx509/data/nist-data2 b/third_party/heimdal/lib/hx509/data/nist-data2 new file mode 100644 index 0000000..491beac --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/nist-data2 @@ -0,0 +1,291 @@ +# 4.1.1 Valid Signatures Test1 - Validate Successfully +0 ValidCertificatePathTest1EE.crt +# 4.1.2 Invalid CA Signature Test2 - Reject - Invalid signature on intermediate certificate +1 InvalidCASignatureTest2EE.crt +# 4.1.3 Invalid EE Signature Test3 - Reject - Invalid signature on end entity certificate +1 InvalidEESignatureTest3EE.crt +# 4.1.4 Valid DSA Signatures Test4 - Reject - Application can not process DSA signatures +1 ValidDSASignaturesTest4EE.crt +# 4.2.1 Invalid CA notBefore Date Test1 - Reject - notBefore date in intermediate certificate is after the current date +1 InvalidCAnotBeforeDateTest1EE.crt +# 4.2.2 Invalid EE notBefore Date Test2 - Reject - notBefore date in end entity certificate is after the current date +1 InvalidEEnotBeforeDateTest2EE.crt +# 4.2.3 Valid pre2000 UTC notBefore Date Test3 - Validate Successfully +0 Validpre2000UTCnotBeforeDateTest3EE.crt +# 4.2.4 Valid GeneralizedTime notBefore Date Test4 - Validate Successfully +0 ValidGeneralizedTimenotBeforeDateTest4EE.crt +# 4.2.5 Invalid CA notAfter Date Test5 - Reject - notAfter date in intermediate certificate is before the current date +1 InvalidCAnotAfterDateTest5EE.crt +# 4.2.6 Invalid EE notAfter Date Test6 - Reject - notAfter date in end entity certificate is before the current date +1 InvalidEEnotAfterDateTest6EE.crt +# 4.2.7 Invalid pre2000 UTC EE notAfter Date Test7 - Reject - notAfter date in end entity certificate is before the current date +1 Invalidpre2000UTCEEnotAfterDateTest7EE.crt +# 4.2.8 Valid GeneralizedTime notAfter Date Test8 - Validate Successfully +0 ValidGeneralizedTimenotAfterDateTest8EE.crt +# 4.3.1 Invalid Name Chaining EE Test1 - Reject - names do not chain +1 InvalidNameChainingTest1EE.crt +# 4.3.2 Invalid Name Chaining Order Test2 - Reject - names do not chain +1 InvalidNameChainingOrderTest2EE.crt +# 4.3.3 Valid Name Chaining Whitespace Test3 - Validate Successfully +0 ValidNameChainingWhitespaceTest3EE.crt +# 4.3.4 Valid Name Chaining Whitespace Test4 - Validate Successfully +0 ValidNameChainingWhitespaceTest4EE.crt +# 4.3.5 Valid Name Chaining Capitalization Test5 - Validate Successfully +0 ValidNameChainingCapitalizationTest5EE.crt +# 4.3.6 Valid Name Chaining UIDs Test6 - Validate Successfully +0 ValidNameUIDsTest6EE.crt +# 4.3.9 Valid UTF8String Encoded Names Test9 - Validate Successfully +0 ValidUTF8StringEncodedNamesTest9EE.crt +# 4.4.1 Missing CRL Test1 - Reject or Warn - status of end entity certificate can not be determined +3 InvalidMissingCRLTest1EE.crt +# 4.4.2 Invalid Revoked CA Test2 - Reject - an intermediate certificate has been revoked. +2 InvalidRevokedCATest2EE.crt +# 4.4.3 Invalid Revoked EE Test3 - Reject - the end entity certificate has been revoked +2 InvalidRevokedEETest3EE.crt +# 4.4.4. Invalid Bad CRL Signature Test4 - Reject or Warn - status of end entity certificate can not be determined +3 InvalidBadCRLSignatureTest4EE.crt +# 4.4.5 Invalid Bad CRL Issuer Name Test5 - Reject or Warn - status of end entity certificate can not be determined +3 InvalidBadCRLIssuerNameTest5EE.crt +# 4.4.6 Invalid Wrong CRL Test6 - Reject or Warn - status of end entity certificate can not be determined +3 InvalidWrongCRLTest6EE.crt +# 4.4.7 Valid Two CRLs Test7 - Validate Successfully +0 ValidTwoCRLsTest7EE.crt +# 4.4.8 Invalid Unknown CRL Entry Extension Test8 - Reject - the end entity certificate has been revoked +2 InvalidUnknownCRLEntryExtensionTest8EE.crt +# 4.4.9 Invalid Unknown CRL Extension Test9 - Reject - the end entity certificate has been revoked +2 InvalidUnknownCRLExtensionTest9EE.crt +# 4.4.10 Invalid Unknown CRL Extension Test10 - Reject or Warn - status of end entity certificate can not be determined +3 InvalidUnknownCRLExtensionTest10EE.crt +# 4.4.11 Invalid Old CRL nextUpdate Test11 - Reject or Warn - status of end entity certificate can not be determined +3 InvalidOldCRLnextUpdateTest11EE.crt +# 4.4.12 Invalid pre2000 CRL nextUpdate Tesst12 - Reject or Warn - status of end entity certificate can not be determined +3 Invalidpre2000CRLnextUpdateTest12EE.crt +# 4.4.13 Valid GeneralizedTime CRL nextUpdate Test13 - Validate Successfully +0 ValidGeneralizedTimeCRLnextUpdateTest13EE.crt +# 4.4.14 Valid Negative Serial Number Test14 - Validate Successfully +0 ValidNegativeSerialNumberTest14EE.crt +# 4.4.15 Invalid Negative Serial Number Test15 - Reject - the end entity certificate has been revoked +2 InvalidNegativeSerialNumberTest15EE.crt +# 4.4.16 Valid Long Serial Number Test16 - Validate Successfully +0 ValidLongSerialNumberTest16EE.crt +# 4.4.17 Valid Long Serial Number Test17 - Validate Successfully +0 ValidLongSerialNumberTest17EE.crt +# 4.4.18 Invalid Long Serial Number Test18 - Reject - the end entity certificate has been revoked +2 InvalidLongSerialNumberTest18EE.crt +# 4.4.19 Valid Separate Certificate and CRL Keys Test19 - Validate Successfully +0 ValidSeparateCertificateandCRLKeysTest19EE.crt +# 4.4.20 Invalid Separate Certificate and CRL Keys Test20 - Reject - the end entity certificate has been revoked +2 InvalidSeparateCertificateandCRLKeysTest20EE.crt +# 4.4.21 Invalid Separate Certificate and CRL Keys Test21 - Reject or Warn - status of end entity certificate can not be determined +3 InvalidSeparateCertificateandCRLKeysTest21EE.crt +# 4.5.1 Valid Basic Self-Issued Old With New Test1 - Validate Successfully +0 ValidBasicSelfIssuedOldWithNewTest1EE.crt +# 4.5.2 Invalid Basic Self-Issued Old With New Test2 - Reject - the end entity certificate has been revoked +2 InvalidBasicSelfIssuedOldWithNewTest2EE.crt +# 4.5.3 Valid Basic Self-Issued New With Old Test3 - Validate Successfully +0 ValidBasicSelfIssuedNewWithOldTest3EE.crt +# 4.5.4 Valid Basic Self-Issued New With Old Test4 - Validate Successfully +0 ValidBasicSelfIssuedNewWithOldTest4EE.crt +# 4.5.5 Invalid Basic Self-Issued New With Old Test5 - Reject - the end entity certificate has been revoked +2 InvalidBasicSelfIssuedNewWithOldTest5EE.crt +# 4.5.6 Valid Basic Self-Issued CRL Signing Key Test6 - Validate Successfully +0 ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt +# 4.5.7 Invalid Basic Self-Issued CRL Signing Key Test7 - Reject - the end entity certificate has been revoked +2 InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt +# 4.5.8 Invalid Basic Self-Issued CRL Signing Key Test8 - Reject - invalid certification path +1 InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt +# 4.6.1 Invalid Missing basicConstraints Test1 - Reject - invalid certification path +1 InvalidMissingbasicConstraintsTest1EE.crt +# 4.6.2 Invalid cA False Test2 - Reject - invalid certification path +1 InvalidcAFalseTest2EE.crt +# 4.6.3 Invalid cA False Test3 - Reject - invalid certification path +1 InvalidcAFalseTest3EE.crt +# 4.6.4 Valid basicConstraints Not Critical Test4 - Validate Successfully +0 ValidbasicConstraintsNotCriticalTest4EE.crt +# 4.6.5 Invalid pathLenConstraint Test5 - Reject - invalid certification path +1 InvalidpathLenConstraintTest5EE.crt +# 4.6.6 Invalid pathLenConstraint Test6 - Reject - invalid certification path +1 InvalidpathLenConstraintTest6EE.crt +# 4.6.7 Valid pathLenConstraint Test7 - Validate Successfully +0 ValidpathLenConstraintTest7EE.crt +# 4.6.8 Valid pathLenConstraint Test8 - Validate Successfully +0 ValidpathLenConstraintTest8EE.crt +# 4.6.9 Invalid pathLenConstraint Test9 - Reject - invalid certification path +1 InvalidpathLenConstraintTest9EE.crt +# 4.6.10 Invalid pathLenConstraint Test10 - Reject - invalid certification path +1 InvalidpathLenConstraintTest10EE.crt +# 4.6.11 Invalid pathLenConstraint Test11 - Reject - invalid certification path +1 InvalidpathLenConstraintTest11EE.crt +# 4.6.12 Invalid pathLenConstraint Test12 - Reject - invalid certification path +1 InvalidpathLenConstraintTest12EE.crt +# 4.6.13 Valid pathLenConstraint Test13 - Validate Successfully +0 ValidpathLenConstraintTest13EE.crt +# 4.6.14 Valid pathLenConstraint Test14 - Validate Successfully +0 ValidpathLenConstraintTest14EE.crt +# 4.6.15 Valid Self-Issued pathLenConstraint Test15 - Validate Successfully +0 ValidSelfIssuedpathLenConstraintTest15EE.crt +# 4.6.16 Invalid Self-Issued pathLenConstraint Test16 - Reject - invalid certification path +1 InvalidSelfIssuedpathLenConstraintTest16EE.crt +# 4.6.17 Valid Self-Issued pathLenConstraint Test17 - Validate Successfully +0 ValidSelfIssuedpathLenConstraintTest17EE.crt +# 4.7.1 Invalid keyUsage Critical keyCertSign False Test1 - Reject - invalid certification path +1 InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt +# 4.7.2 Invalid keyUsage Not Critical keyCertSign False Test2 - Reject - invalid certification path +1 InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt +# 4.7.3 Valid keyUsage Not Critical Test3 - Validate Successfully +0 ValidkeyUsageNotCriticalTest3EE.crt +# 4.7.4 Invalid keyUsage Critical cRLSign False Test4 - Reject - invalid certification path +1 InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt +# 4.7.5 Invalid keyUsage Not Critical cRLSign False Test5 - Reject - invalid certification path +1 InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt +0 UserNoticeQualifierTest19EE.crt +# 4.10.1 Valid Policy Mapping Test1, subtest 1 - Reject - unrecognized critical extension [Test using the default settings (i.e., <i>initial-policy-set</i> = <i>any-policy</i>) +1 InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt +# 4.11.2 Valid inhibitPolicyMapping Test2 - Reject - unrecognized critical extension +1 ValidinhibitPolicyMappingTest2EE.crt +# 4.12.2 Valid inhibitAnyPolicy Test2 - Reject - unrecognized critical extension +1 ValidinhibitAnyPolicyTest2EE.crt +# 4.13.1 Valid DN nameConstraints Test1 - Validate Successfully +0 ValidDNnameConstraintsTest1EE.crt +# 4.13.2 Invalid DN nameConstraints Test2 - Reject - name constraints violation +1 InvalidDNnameConstraintsTest2EE.crt +# 4.13.3 Invalid DN nameConstraints Test3 - Reject - name constraints violation +1 InvalidDNnameConstraintsTest3EE.crt +# 4.13.4 Valid DN nameConstraints Test4 - Validate Successfully +0 ValidDNnameConstraintsTest4EE.crt +# 4.13.5 Valid DN nameConstraints Test5 - Validate Successfully +0 ValidDNnameConstraintsTest5EE.crt +# 4.13.6 Valid DN nameConstraints Test6 - Validate Successfully +0 ValidDNnameConstraintsTest6EE.crt +# 4.13.7 Invalid DN nameConstraints Test7 - Reject - name constraints violation +1 InvalidDNnameConstraintsTest7EE.crt +# 4.13.8 Invalid DN nameConstraints Test8 - Reject - name constraints violation +1 InvalidDNnameConstraintsTest8EE.crt +# 4.13.9 Invalid DN nameConstraints Test9 - Reject - name constraints violation +1 InvalidDNnameConstraintsTest9EE.crt +# 4.13.10 Invalid DN nameConstraints Test10 - Reject - name constraints violation +1 InvalidDNnameConstraintsTest10EE.crt +# 4.13.11 Valid DN nameConstraints Test11 - Validate Successfully +0 ValidDNnameConstraintsTest11EE.crt +# 4.13.12 Invalid DN nameConstraints Test12 - Reject - name constraints violation +1 InvalidDNnameConstraintsTest12EE.crt +# 4.13.13 Invalid DN nameConstraints Test13 - Reject - name constraints violation +1 InvalidDNnameConstraintsTest13EE.crt +# 4.13.14 Valid DN nameConstraints Test14 - Validate Successfully +0 ValidDNnameConstraintsTest14EE.crt +# 4.13.15 Invalid DN nameConstraints Test15 - Reject - name constraints violation +1 InvalidDNnameConstraintsTest15EE.crt +# 4.13.16 Invalid DN nameConstraints Test16 - Reject - name constraints violation +1 InvalidDNnameConstraintsTest16EE.crt +# 4.13.17 Invalid DN nameConstraints Test17 - Reject - name constraints violation +1 InvalidDNnameConstraintsTest17EE.crt +# 4.13.18 Valid DN nameConstraints Test18 - Validate Successfully +0 ValidDNnameConstraintsTest18EE.crt +# 4.13.19 Valid Self-Issued DN nameConstraints Test19 - Validate Successfully +0 ValidDNnameConstraintsTest19EE.crt +# 4.13.20 Invalid Self-Issued DN nameConstraints Test20 - Reject - name constraints violation +1 InvalidDNnameConstraintsTest20EE.crt +# 4.13.21 Valid RFC822 nameConstraints Test21 - Validate Successfully +0 ValidRFC822nameConstraintsTest21EE.crt +# 4.13.22 Invalid RFC822 nameConstraints Test22 - Reject - name constraints violation +1 InvalidRFC822nameConstraintsTest22EE.crt +# 4.13.23 Valid RFC822 nameConstraints Test23 - Validate Successfully +0 ValidRFC822nameConstraintsTest23EE.crt +# 4.13.24 Invalid RFC822 nameConstraints Test24 - Reject - name constraints violation +1 InvalidRFC822nameConstraintsTest24EE.crt +# 4.13.25 Valid RFC822 nameConstraints Test25 - Validate Successfully +0 ValidRFC822nameConstraintsTest25EE.crt +# 4.13.26 Invalid RFC822 nameConstraints Test26 - Reject - name constraints violation +1 InvalidRFC822nameConstraintsTest26EE.crt +# 4.13.27 Valid DN and RFC822 nameConstraints Test27 - Validate Successfully +0 ValidDNandRFC822nameConstraintsTest27EE.crt +# 4.13.28 Invalid DN and RFC822 nameConstraints Test28 - Reject - name constraints violation +1 InvalidDNandRFC822nameConstraintsTest28EE.crt +# 4.13.29 Invalid DN and RFC822 nameConstraints Test29 - Reject - name constraints violation +1 InvalidDNandRFC822nameConstraintsTest29EE.crt +# 4.13.30 Valid DNS nameConstraints Test30 - Validate Successfully +0 ValidDNSnameConstraintsTest30EE.crt +# 4.13.31 Invalid DNS nameConstraints Test31 - Reject - name constraints violation +1 InvalidDNSnameConstraintsTest31EE.crt +# 4.13.32 Valid DNS nameConstraints Test32 - Validate Successfully +0 ValidDNSnameConstraintsTest32EE.crt +# 4.13.33 Invalid DNS nameConstraints Test33 - Reject - name constraints violation +1 InvalidDNSnameConstraintsTest33EE.crt +# 4.13.34 Valid URI nameConstraints Test34 - Validate Successfully +0 ValidURInameConstraintsTest34EE.crt +# 4.13.35 Invalid URI nameConstraints Test35 - Reject - name constraints violation +1 InvalidURInameConstraintsTest35EE.crt +# 4.13.36 Valid URI nameConstraints Test36 - Validate Successfully +0 ValidURInameConstraintsTest36EE.crt +# 4.13.37 Invalid URI nameConstraints Test37 - Reject - name constraints violation +1 InvalidURInameConstraintsTest37EE.crt +# 4.13.38 Invalid DNS nameConstraints Test38 - Reject - name constraints violation +1 InvalidDNSnameConstraintsTest38EE.crt +# 4.14.1 Valid distributionPoint Test1 - Validate Successfully +0 ValiddistributionPointTest1EE.crt +# 4.14.2 Invalid distributionPoint Test2 - Reject - end entity certificate has been revoked +2 InvaliddistributionPointTest2EE.crt +# 4.14.3 Invalid distributionPoint Test3 - Reject or Warn - status of end entity certificate can not be determined +3 InvaliddistributionPointTest3EE.crt +# 4.14.4 Valid distributionPoint Test4 - Validate Successfully +0 ValiddistributionPointTest4EE.crt +# 4.14.5 Valid distributionPoint Test5 - Validate Successfully +0 ValiddistributionPointTest5EE.crt +# 4.14.6 Invalid distributionPoint Test6 - Reject - end entity certificate has been revoked +2 InvaliddistributionPointTest6EE.crt +# 4.14.7 Valid distributionPoint Test7 - Validate Successfully +0 ValiddistributionPointTest7EE.crt +# 4.14.8 Invalid distributionPoint Test8 - Reject or Warn - status of end entity certificate can not be determined +3 InvaliddistributionPointTest8EE.crt +# 4.14.9 Invalid distributionPoint Test9 - Reject or Warn - status of end entity certificate can not be determined +3 InvaliddistributionPointTest9EE.crt +# 4.14.10 Valid No issuingDistributionPoint Test10 - Validate Successfully +0 ValidNoissuingDistributionPointTest10EE.crt +# 4.14.11 Invalid onlyContainsUserCerts CRL Test11 - Reject or Warn - status of end entity certificate can not be determined +3 InvalidonlyContainsUserCertsTest11EE.crt +# 4.14.12 Invalid onlyContainsCACerts CRL Test12 - Reject or Warn - status of end entity certificate can not be determined +3 InvalidonlyContainsCACertsTest12EE.crt +# 4.14.13 Valid onlyContainsCACerts CRL Test13 - Validate Successfully +0 ValidonlyContainsCACertsTest13EE.crt +# 4.14.14 Invalid onlyContainsAttributeCerts Test14 - Reject or Warn - status of end entity certificate can not be determined +3 InvalidonlyContainsAttributeCertsTest14EE.crt +# 4.14.15 Invalid onlySomeReasons Test15 - Reject - end entity certificate has been revoked +2 InvalidonlySomeReasonsTest15EE.crt +# 4.14.16 Invalid onlySomeReasons Test16 - Reject - end entity certificate is on hold +2 InvalidonlySomeReasonsTest16EE.crt +# 4.14.17 Invalid onlySomeReasons Test17 - Reject or Warn - status of end entity certificate can not be determined +3 InvalidonlySomeReasonsTest17EE.crt +# 4.14.18 Valid onlySomeReasons Test18 - Validate Successfully +0 ValidonlySomeReasonsTest18EE.crt +# 4.14.19 Valid onlySomeReasons Test19 - Validate Successfully +0 ValidonlySomeReasonsTest19EE.crt +# 4.14.20 Invalid onlySomeReasons Test20 - Reject - end entity certificate has been revoked +2 InvalidonlySomeReasonsTest20EE.crt +# 4.14.21 Invalid onlySomeReasons Test21 - Reject - end entity certificate has been revoked +2 InvalidonlySomeReasonsTest21EE.crt +# 4.14.24 Valid IDP with indirectCRL Test24 - Reject or Warn - status of end entity certificate can not be determined +3 ValidIDPwithindirectCRLTest24EE.crt +# 4.15.1 Invalid deltaCRLIndicator No Base Test1 - Reject or Warn - status of end entity certificate can not be determined +3 InvaliddeltaCRLIndicatorNoBaseTest1EE.crt +# 4.15.2 Valid delta-CRL Test2 - Validate Successfully +0 ValiddeltaCRLTest2EE.crt +# 4.15.3 Invalid delta-CRL Test3 - Reject - end entity certificate has been revoked +2 InvaliddeltaCRLTest3EE.crt +# 4.15.4 Invalid delta-CRL Test4 - Reject - end entity certificate has been revoked +2 InvaliddeltaCRLTest4EE.crt +# 4.15.5 Valid delta-CRL Test5 - Validate Successfully +0 ValiddeltaCRLTest5EE.crt +# 4.15.6 Invalid delta-CRL Test6 - Reject - end entity certificate has been revoked +2 InvaliddeltaCRLTest6EE.crt +# 4.15.7 Valid delta-CRL Test7 - Validate Successfully +0 ValiddeltaCRLTest7EE.crt +# 4.15.8 Valid delta-CRL Test8 - Validate Successfully +0 ValiddeltaCRLTest8EE.crt +# 4.15.9 Invalid delta-CRL Test9 - Reject - end entity certificate has been revoked +2 InvaliddeltaCRLTest9EE.crt +# 4.15.10 Invalid delta-CRL Test10 - Reject or Warn - status of end entity certificate can not be determined +3 InvaliddeltaCRLTest10EE.crt +# 4.16.1 Valid Unknown Not Critical Certificate Extension Test1 - Validate Successfully +0 ValidUnknownNotCriticalCertificateExtensionTest1EE.crt +# 4.16.2 Invalid Unknown Critical Certificate Extension Test2 - Reject - unrecognized critical extension +1 InvalidUnknownCriticalCertificateExtensionTest2EE.crt diff --git a/third_party/heimdal/lib/hx509/data/nist-result2 b/third_party/heimdal/lib/hx509/data/nist-result2 new file mode 100644 index 0000000..93a22e7 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/nist-result2 @@ -0,0 +1,31 @@ +# $Id$ +# id FAIL +4.2.8 EITHER depeneds on if time_t is 64 bit or not +4.3.5 FAIL +4.4.13 EITHER depeneds on if time_t is 64 bit or not +4.5.1 FAIL +4.5.4 FAIL +4.5.6 FAIL +4.6.15 FAIL +4.6.17 FAIL +4.11.2 FAIL +4.12.2 FAIL +4.13.19 FAIL +4.13.21 FAIL +4.13.23 FAIL +4.13.26 FAIL +4.13.27 FAIL +4.13.30 FAIL +4.13.33 FAIL +4.13.34 FAIL +4.13.37 FAIL +4.14.1 FAIL +4.14.4 FAIL +4.14.5 FAIL +4.14.7 FAIL +4.14.13 FAIL +4.14.18 FAIL +4.14.19 FAIL +4.15.4 FAIL +4.15.5 FAIL +4.16.2 FAIL diff --git a/third_party/heimdal/lib/hx509/data/no-proxy-test.crt b/third_party/heimdal/lib/hx509/data/no-proxy-test.crt new file mode 100644 index 0000000..5f27bcd --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/no-proxy-test.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFEzCCAvugAwIBAgIJAKQmPUkmhyKiMA0GCSqGSIb3DQEBCwUAMCExCzAJBgNV +BAYTAlNFMRIwEAYDVQQDDAlUZXN0IGNlcnQwIBcNMTkwMzIyMjIyNTEzWhgPMjUx +ODExMjEyMjI1MTNaMDQxCzAJBgNVBAYTAlNFMRIwEAYDVQQDDAlUZXN0IGNlcnQx +ETAPBgNVBAMMCG5vLXByb3h5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC +AgEA1wY5NrUAYbdIiJyOwEG5zo6892LuPxYrJ39qy0868pQMPuViT3IjP8fOockf +IHFqM1M/rYEKBCaHm3W5d0+QET1T3pJq7eOTuG8Ep4BiMDm2mD0VeWOCeLJjfnuR +8WPG3Fz//55NBCByMc4as5+Gw9b6z6Mh8pFMyz4zyMQI420Gss9hHoTiD9o4fhM4 +U5M+l+gvVYmvLhZ0Z8hIJAqnlRJoIKeEbcHS1qIqkN0vkdRZc5usJmxhpJi8SjTS +pGiP53QDmGDJMHd5Fsfyv98n6T6fIkf+O2sAVnxdgOBIyYibdMH021/UzbXZHoDK +Nx5HH9lr1R9vE5fy969yCQ10lgaNmlp68j8/5B8QPeRbe29DQ1rRBzheji1kkxbg +8FU7GKu92GHrDhK5dasl7tH3qx4WKOAD4ENJI4vSDWo/IxkKYLLuNIMcVhmGORGl +IvxaDVxr5wHdGgpBJwc2BxcHU6/8cuYGDewR2h/TWb6jTVmfq7lx+fefEkTDmOxI +WbXwGtbZqqX5EzWp3VTBakONdRjJwxg3MShWJ1ZhYawzeTwZg3FOIn9W2tLkPNU7 +Ly/fZMBD6qJ5X/0gJGkx9QRlANMJnj0POaBvIyzkGz95QlyIoiAJyuzCKbX5WQdd +jy1drnB2VdAjWyAjUP+9JsMJJKyLYOWxvemE1yAIIL9yjVMCAwEAAaM5MDcwCQYD +VR0TBAIwADALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFN8mmgQlHmnWopRs35laOYZ9 +/02LMA0GCSqGSIb3DQEBCwUAA4ICAQB6dmCcY2XRzeZz2CQ2DdGJRyBDdHFf7W3O +4Tk/w2ZQLFx6BwttOB94LcaVFRUHp9arkNDH6ne9ntQ1LZ3fPoRR4RXwQO8c+pIf +ZDWPEr7Exv1F1zrjAEHx2UcP1pu4PU9PDqmGs2BarnHgKotfY8AXdJkl1g128LIQ +WOmQFyI6Ny//4MT/5YB6OSr2zzrKz5FyGxKSG49xfPSSAf3mHAUxHzBJ1orpHIpo +zQcrt6oRbi9G9cKVYTEVRVM2CgqMJwBUH7d9BRIab4hp7lqynFJKg3uOH90cmms1 +dY5NRmy+jmAqveEGvCw2+vmHtbj5NikwUBnRqZGW/XHLSj8niCtO2PT30xzpDiEa +iYBGyuETV5vwFIbucdbenaBrrbvumr4lWqhjadQVwjhNcqdmhIxuGGXF/XGG5+do +hFaYD5fguyfQDGaeFQIipPEyZcx0QcGA77g7eKYgPyBFZxGHS7P1x1GrchZIOH1q +W59AuSwxKWGEAM2tlp2+Esp3Zj8UBy2nL9fXRyDEMerCuJUcbCLODGYDc0/s/7Cs +G8ZNK+GXs68CgxJCbxY5uUcYQyVpRFi62jvghuPGQkxytQ/GWM+q94ncr8I2+lsO +kTcdzYbAapst+XoPL9enQwAkw4yksJ8Rx2P2TDRAZl58+utRrdQyL0oD9cJy57LE +cpMYhZWsyQ== +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/no-proxy-test.key b/third_party/heimdal/lib/hx509/data/no-proxy-test.key new file mode 100644 index 0000000..9f30400 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/no-proxy-test.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +vMvFV9XqcWhoGHKX/S/Hmjljr7ln1Dc= +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/ocsp-req1.der b/third_party/heimdal/lib/hx509/data/ocsp-req1.der Binary files differnew file mode 100644 index 0000000..e536ebb --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/ocsp-req1.der diff --git a/third_party/heimdal/lib/hx509/data/ocsp-req2.der b/third_party/heimdal/lib/hx509/data/ocsp-req2.der Binary files differnew file mode 100644 index 0000000..e224fa6 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/ocsp-req2.der diff --git a/third_party/heimdal/lib/hx509/data/ocsp-resp1-2.der b/third_party/heimdal/lib/hx509/data/ocsp-resp1-2.der Binary files differnew file mode 100644 index 0000000..98d88e4 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/ocsp-resp1-2.der diff --git a/third_party/heimdal/lib/hx509/data/ocsp-resp1-3.der b/third_party/heimdal/lib/hx509/data/ocsp-resp1-3.der Binary files differnew file mode 100644 index 0000000..4c65016 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/ocsp-resp1-3.der diff --git a/third_party/heimdal/lib/hx509/data/ocsp-resp1-ca.der b/third_party/heimdal/lib/hx509/data/ocsp-resp1-ca.der Binary files differnew file mode 100644 index 0000000..228918c --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/ocsp-resp1-ca.der diff --git a/third_party/heimdal/lib/hx509/data/ocsp-resp1-keyhash.der b/third_party/heimdal/lib/hx509/data/ocsp-resp1-keyhash.der Binary files differnew file mode 100644 index 0000000..250a1f1 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/ocsp-resp1-keyhash.der diff --git a/third_party/heimdal/lib/hx509/data/ocsp-resp1-ocsp-no-cert.der b/third_party/heimdal/lib/hx509/data/ocsp-resp1-ocsp-no-cert.der Binary files differnew file mode 100644 index 0000000..6ebbd84 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/ocsp-resp1-ocsp-no-cert.der diff --git a/third_party/heimdal/lib/hx509/data/ocsp-resp1-ocsp.der b/third_party/heimdal/lib/hx509/data/ocsp-resp1-ocsp.der Binary files differnew file mode 100644 index 0000000..c97654a --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/ocsp-resp1-ocsp.der diff --git a/third_party/heimdal/lib/hx509/data/ocsp-resp1.der b/third_party/heimdal/lib/hx509/data/ocsp-resp1.der Binary files differnew file mode 100644 index 0000000..8546eba --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/ocsp-resp1.der diff --git a/third_party/heimdal/lib/hx509/data/ocsp-resp2.der b/third_party/heimdal/lib/hx509/data/ocsp-resp2.der Binary files differnew file mode 100644 index 0000000..d731f38 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/ocsp-resp2.der diff --git a/third_party/heimdal/lib/hx509/data/ocsp-responder.crt b/third_party/heimdal/lib/hx509/data/ocsp-responder.crt new file mode 100644 index 0000000..753ca56 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/ocsp-responder.crt @@ -0,0 +1,119 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Mar 22 22:25:01 2019 GMT + Not After : Nov 21 22:25:01 2518 GMT + Subject: C=SE, CN=OCSP responder + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:b1:21:1d:c9:2b:44:9e:62:fe:13:94:ea:a1:e1: + cd:17:0e:bb:4d:1c:62:27:ee:d3:f7:61:c8:26:c1: + 0f:45:fc:10:d8:39:c3:da:86:a0:00:30:d7:ad:86: + ff:c6:36:6c:f5:e2:26:8c:f6:76:1b:d0:09:b6:a5: + f8:cb:d5:88:fc:ca:ca:28:49:ed:64:2b:f3:88:4e: + 8e:ec:7c:63:b8:75:6a:cc:73:b6:66:6c:c3:7c:e4: + d7:50:95:88:12:84:e7:5c:50:87:db:4c:bf:91:98: + b1:3a:44:57:0b:1a:7a:f1:93:e3:4c:69:8b:9f:d7: + b9:20:8d:0e:cb:ff:de:38:6f:6a:91:55:1a:6f:a6: + 82:1d:05:f6:fc:46:8c:83:8b:ab:6e:3f:6a:6f:c5: + 0c:cc:ff:3c:78:74:d4:f8:56:be:59:60:d5:3f:4d: + 3e:e4:e1:4b:2d:c5:2a:d1:6a:7a:21:b9:6e:61:10: + 03:79:88:5b:74:f4:29:0d:56:d3:6b:d5:7d:8c:59: + 5d:4e:89:0d:a3:a6:8b:43:28:e8:e2:f1:bb:d5:eb: + 65:9b:c2:d6:62:aa:df:66:d5:92:dd:84:6c:29:28: + 1a:e8:29:b3:09:d1:45:14:44:cb:30:03:73:3a:94: + a3:a3:24:89:15:fb:ca:e0:a6:62:35:48:f8:92:50: + 3a:ff:17:d8:4a:1e:a0:9c:d9:68:cc:21:e1:c9:36: + d1:47:bc:f1:56:3e:87:18:10:0d:f5:56:9a:c9:79: + 16:c0:08:a0:59:65:b2:00:dd:9a:e9:97:e7:8f:85: + ee:cd:0d:20:5e:2d:58:ff:8e:e3:ce:4f:36:65:c3: + f1:88:39:dd:34:29:db:8c:ed:6e:c8:7b:30:ad:49: + 58:e6:f9:5b:85:46:0a:04:0f:9e:ea:ca:a8:2a:35: + 0d:66:f3:48:b6:e3:c7:e0:e8:a3:ed:6c:f3:e4:cd: + 1d:45:f3:e2:2c:6c:5b:91:b8:26:dd:49:d4:78:d3: + 4e:57:3a:b5:af:cd:3a:05:d5:89:63:f5:bc:73:1f: + 26:cc:2c:4b:2d:81:b3:5d:49:28:04:46:f8:24:5a: + 68:1d:06:1b:2d:be:56:f9:b3:f4:d1:50:2f:95:9b: + 9f:45:c7:62:35:bc:46:a9:df:c6:45:21:e9:1c:7d: + a8:2e:b1:87:91:0b:7c:fb:97:52:31:f9:41:73:ba: + 83:22:4a:80:f9:ff:f1:95:74:79:f7:20:95:f0:17: + 20:7d:ac:55:e8:b0:c6:b2:a6:56:c6:c0:cf:3d:78: + d5:9e:37:41:b4:78:aa:30:f0:2d:59:7c:6a:c8:68: + cc:91:09:13:f8:9f:04:e3:a9:86:c2:74:ba:f6:32: + 44:0d:bd + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Extended Key Usage: + OCSP No Check, OCSP Signing + X509v3 Subject Key Identifier: + D0:3C:E8:05:07:BB:9A:96:36:88:44:AA:9A:4F:62:9E:9F:33:5B:03 + Signature Algorithm: sha1WithRSAEncryption + c0:72:d2:af:26:74:de:f8:7c:96:bf:ab:d2:ed:95:d9:bb:0b: + 07:31:8a:4b:21:f0:b5:7e:ab:b4:50:b0:af:bf:96:64:ce:38: + 99:3d:f3:26:02:4d:5a:da:71:ad:6d:a6:f7:fc:5e:46:16:3d: + 9e:cf:95:a3:5d:0c:4a:64:a1:84:88:b0:31:0e:eb:54:cb:99: + 42:45:09:92:ea:b7:74:f5:fb:ff:c6:91:31:27:bd:54:55:9f: + 6c:bb:e2:45:4a:33:ed:00:a5:4e:e2:7b:2c:98:f1:3b:bc:f2: + 87:33:e5:22:d8:fc:a8:4c:90:e2:df:ce:48:c8:3c:56:43:6c: + ac:f1:f6:e0:75:c2:a7:f9:33:87:4e:75:a6:22:17:78:32:88: + aa:f9:2a:40:4c:e0:25:6c:4c:0c:cb:6f:1a:7b:13:0d:35:a6: + 23:86:42:75:3c:c1:69:c1:c5:79:77:51:4b:19:14:e7:4b:f9: + df:0b:30:aa:c4:97:84:6e:57:7b:00:b3:a5:31:c6:9f:17:f1: + b0:4c:81:f7:e6:df:e8:c0:d2:91:03:c2:e3:dd:94:c4:f0:ee: + 1c:73:1c:33:ae:91:60:fe:cf:48:08:0a:95:c1:95:28:af:31: + 23:a6:2a:1c:d1:6c:7f:68:e8:a9:a4:27:8f:6f:29:33:a9:48: + 0c:03:8f:fa:b5:ef:2a:9a:ce:ed:ba:74:39:88:ef:3b:d9:93: + 77:34:30:d1:a3:5c:9d:f1:3c:30:19:c2:ca:2e:41:5b:23:bb: + 6a:67:35:e3:e2:c6:6e:a0:3e:76:50:db:6b:ee:02:98:81:bf: + 75:ac:3a:78:4f:f4:fb:d1:7a:1f:85:1a:24:cd:b8:06:7e:95: + 28:85:2a:c6:41:23:35:08:31:59:ce:ad:a3:23:1a:7a:11:26: + d9:45:57:bf:ea:e0:72:3a:f8:48:e0:c1:5c:b3:20:93:b5:1a: + 93:75:ef:f3:19:9d:ed:5d:9f:81:73:21:02:96:fa:ee:c9:4c: + c7:95:1b:aa:65:b9:69:15:3c:ef:b3:f6:e1:f5:89:78:05:50: + d3:54:c4:c9:40:e5:5f:3e:bd:36:d2:0e:27:99:5e:83:e5:4b: + bf:72:84:13:64:8d:d9:db:69:8b:04:37:e8:db:22:46:29:84: + 08:83:40:34:d8:e0:bf:cc:5c:7c:b2:bd:c5:38:7d:59:e6:9d: + 8a:78:87:08:13:6f:a5:7d:2f:88:80:ce:e5:86:38:6f:53:b8: + 99:ba:f5:21:9e:8f:5f:aa:3a:07:73:9b:02:f1:97:1f:8b:52: + 53:5e:24:af:d7:b9:a4:3f:4e:64:c8:62:26:b3:c0:44:dd:bb: + 29:8c:b5:66:05:5d:fd:f7 +-----BEGIN CERTIFICATE----- +MIIFJjCCAw6gAwIBAgIBATANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMCAXDTE5MDMyMjIyMjUwMVoYDzI1 +MTgxMTIxMjIyNTAxWjAmMQswCQYDVQQGEwJTRTEXMBUGA1UEAwwOT0NTUCByZXNw +b25kZXIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCxIR3JK0SeYv4T +lOqh4c0XDrtNHGIn7tP3YcgmwQ9F/BDYOcPahqAAMNethv/GNmz14iaM9nYb0Am2 +pfjL1Yj8ysooSe1kK/OITo7sfGO4dWrMc7ZmbMN85NdQlYgShOdcUIfbTL+RmLE6 +RFcLGnrxk+NMaYuf17kgjQ7L/944b2qRVRpvpoIdBfb8RoyDi6tuP2pvxQzM/zx4 +dNT4Vr5ZYNU/TT7k4UstxSrRanohuW5hEAN5iFt09CkNVtNr1X2MWV1OiQ2jpotD +KOji8bvV62WbwtZiqt9m1ZLdhGwpKBroKbMJ0UUURMswA3M6lKOjJIkV+8rgpmI1 +SPiSUDr/F9hKHqCc2WjMIeHJNtFHvPFWPocYEA31VprJeRbACKBZZbIA3Zrpl+eP +he7NDSBeLVj/juPOTzZlw/GIOd00KduM7W7IezCtSVjm+VuFRgoED57qyqgqNQ1m +80i248fg6KPtbPPkzR1F8+IsbFuRuCbdSdR4005XOrWvzToF1Ylj9bxzHybMLEst +gbNdSSgERvgkWmgdBhstvlb5s/TRUC+Vm59Fx2I1vEap38ZFIekcfagusYeRC3z7 +l1Ix+UFzuoMiSoD5//GVdHn3IJXwFyB9rFXosMayplbGwM89eNWeN0G0eKow8C1Z +fGrIaMyRCRP4nwTjqYbCdLr2MkQNvQIDAQABo1kwVzAJBgNVHRMEAjAAMAsGA1Ud +DwQEAwIF4DAeBgNVHSUEFzAVBgkrBgEFBQcwAQUGCCsGAQUFBwMJMB0GA1UdDgQW +BBTQPOgFB7ualjaIRKqaT2KenzNbAzANBgkqhkiG9w0BAQUFAAOCAgEAwHLSryZ0 +3vh8lr+r0u2V2bsLBzGKSyHwtX6rtFCwr7+WZM44mT3zJgJNWtpxrW2m9/xeRhY9 +ns+Vo10MSmShhIiwMQ7rVMuZQkUJkuq3dPX7/8aRMSe9VFWfbLviRUoz7QClTuJ7 +LJjxO7zyhzPlItj8qEyQ4t/OSMg8VkNsrPH24HXCp/kzh051piIXeDKIqvkqQEzg +JWxMDMtvGnsTDTWmI4ZCdTzBacHFeXdRSxkU50v53wswqsSXhG5XewCzpTHGnxfx +sEyB9+bf6MDSkQPC492UxPDuHHMcM66RYP7PSAgKlcGVKK8xI6YqHNFsf2joqaQn +j28pM6lIDAOP+rXvKprO7bp0OYjvO9mTdzQw0aNcnfE8MBnCyi5BWyO7amc14+LG +bqA+dlDba+4CmIG/daw6eE/0+9F6H4UaJM24Bn6VKIUqxkEjNQgxWc6toyMaehEm +2UVXv+rgcjr4SODBXLMgk7Uak3Xv8xmd7V2fgXMhApb67slMx5UbqmW5aRU877P2 +4fWJeAVQ01TEyUDlXz69NtIOJ5leg+VLv3KEE2SN2dtpiwQ36NsiRimECINANNjg +v8xcfLK9xTh9WeadiniHCBNvpX0viIDO5YY4b1O4mbr1IZ6PX6o6B3ObAvGXH4tS +U14kr9e5pD9OZMhiJrPARN27KYy1ZgVd/fc= +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/ocsp-responder.key b/third_party/heimdal/lib/hx509/data/ocsp-responder.key new file mode 100644 index 0000000..140aaf8 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/ocsp-responder.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +SSGDNVUC8knNaz9M5HYwvqUl1if8yg== +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/openssl.1.0.cnf b/third_party/heimdal/lib/hx509/data/openssl.1.0.cnf new file mode 100644 index 0000000..b014656 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/openssl.1.0.cnf @@ -0,0 +1,190 @@ +oid_section = new_oids + +[new_oids] +pkkdcekuoid = 1.3.6.1.5.2.3.5 + +[ca] + +default_ca = user + +[usr] +database = index.txt +serial = serial +x509_extensions = usr_cert +default_md=sha1 +policy = policy_match +email_in_dn = no +certs = . + +[ocsp] +database = index.txt +serial = serial +x509_extensions = ocsp_cert +default_md=sha1 +policy = policy_match +email_in_dn = no +certs = . + +[usr_ke] +database = index.txt +serial = serial +x509_extensions = usr_cert_ke +default_md=sha1 +policy = policy_match +email_in_dn = no +certs = . + +[usr_ds] +database = index.txt +serial = serial +x509_extensions = usr_cert_ds +default_md=sha1 +policy = policy_match +email_in_dn = no +certs = . + +[pkinit_client] +database = index.txt +serial = serial +x509_extensions = pkinit_client_cert +default_md=sha1 +policy = policy_match +email_in_dn = no +certs = . + +[pkinit_kdc] +database = index.txt +serial = serial +x509_extensions = pkinit_kdc_cert +default_md=sha1 +policy = policy_match +email_in_dn = no +certs = . + +[https] +database = index.txt +serial = serial +x509_extensions = https_cert +default_md=sha1 +policy = policy_match +email_in_dn = no +certs = . + +[subca] +database = index.txt +serial = serial +x509_extensions = v3_ca +default_md=sha1 +policy = policy_match +email_in_dn = no +certs = . + + +[req] +distinguished_name = req_distinguished_name +x509_extensions = v3_ca # The extensions to add to the self signed cert + +string_mask = utf8only + +[v3_ca] + +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid:always,issuer:always +basicConstraints = CA:true +keyUsage = cRLSign, keyCertSign, keyEncipherment, nonRepudiation, digitalSignature + +[usr_cert] +basicConstraints=CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +subjectKeyIdentifier = hash + +[usr_cert_ke] +basicConstraints=CA:FALSE +keyUsage = nonRepudiation, keyEncipherment +subjectKeyIdentifier = hash + +[proxy_cert] +basicConstraints=CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +subjectKeyIdentifier = hash +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:0,policy:text:foo + +[pkinitc_principals] +princ1 = GeneralString:bar + +[pkinitc_principal_seq] +name_type = EXP:0,INTEGER:1 +name_string = EXP:1,SEQUENCE:pkinitc_principals + +[pkinitc_princ_name] +realm = EXP:0,GeneralString:TEST.H5L.SE +principal_name = EXP:1,SEQUENCE:pkinitc_principal_seq + +[pkinit_client_cert] +basicConstraints=CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +subjectKeyIdentifier = hash +subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:pkinitc_princ_name + +[https_cert] +basicConstraints=CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#extendedKeyUsage = https-server XXX +subjectKeyIdentifier = hash + +[pkinit_kdc_cert] +basicConstraints=CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = pkkdcekuoid +subjectKeyIdentifier = hash +subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:pkinitkdc_princ_name + +[pkinitkdc_princ_name] +realm = EXP:0,GeneralString:TEST.H5L.SE +principal_name = EXP:1,SEQUENCE:pkinitkdc_principal_seq + +[pkinitkdc_principal_seq] +name_type = EXP:0,INTEGER:1 +name_string = EXP:1,SEQUENCE:pkinitkdc_principals + +[pkinitkdc_principals] +princ1 = GeneralString:krbtgt +princ2 = GeneralString:TEST.H5L.SE + +[proxy10_cert] +basicConstraints=CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +subjectKeyIdentifier = hash +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:10,policy:text:foo + +[usr_cert_ds] +basicConstraints=CA:FALSE +keyUsage = nonRepudiation, digitalSignature +subjectKeyIdentifier = hash + +[ocsp_cert] +basicConstraints=CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +# ocsp-nocheck and kp-OCSPSigning +extendedKeyUsage = 1.3.6.1.5.5.7.48.1.5, 1.3.6.1.5.5.7.3.9 +subjectKeyIdentifier = hash + +[req_distinguished_name] +countryName = Country Name (2 letter code) +countryName_default = SE +countryName_min = 2 +countryName_max = 2 + +organizationalName = Organizational Unit Name (eg, section) + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +#[req_attributes] +#challengePassword = A challenge password +#challengePassword_min = 4 +#challengePassword_max = 20 + +[policy_match] +countryName = match +commonName = supplied diff --git a/third_party/heimdal/lib/hx509/data/openssl.1.1.cnf b/third_party/heimdal/lib/hx509/data/openssl.1.1.cnf new file mode 100644 index 0000000..110073f --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/openssl.1.1.cnf @@ -0,0 +1,185 @@ +[ca] + +default_ca = user + +[usr] +database = index.txt +serial = serial +x509_extensions = usr_cert +default_md=sha1 +policy = policy_match +email_in_dn = no +certs = . + +[ocsp] +database = index.txt +serial = serial +x509_extensions = ocsp_cert +default_md=sha1 +policy = policy_match +email_in_dn = no +certs = . + +[usr_ke] +database = index.txt +serial = serial +x509_extensions = usr_cert_ke +default_md=sha1 +policy = policy_match +email_in_dn = no +certs = . + +[usr_ds] +database = index.txt +serial = serial +x509_extensions = usr_cert_ds +default_md=sha1 +policy = policy_match +email_in_dn = no +certs = . + +[pkinit_client] +database = index.txt +serial = serial +x509_extensions = pkinit_client_cert +default_md=sha1 +policy = policy_match +email_in_dn = no +certs = . + +[pkinit_kdc] +database = index.txt +serial = serial +x509_extensions = pkinit_kdc_cert +default_md=sha1 +policy = policy_match +email_in_dn = no +certs = . + +[https] +database = index.txt +serial = serial +x509_extensions = https_cert +default_md=sha1 +policy = policy_match +email_in_dn = no +certs = . + +[subca] +database = index.txt +serial = serial +x509_extensions = v3_ca +default_md=sha1 +policy = policy_match +email_in_dn = no +certs = . + + +[req] +distinguished_name = req_distinguished_name +x509_extensions = v3_ca # The extensions to add to the self signed cert + +string_mask = utf8only + +[v3_ca] + +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid:always,issuer:always +basicConstraints = CA:true +keyUsage = cRLSign, keyCertSign, keyEncipherment, nonRepudiation, digitalSignature + +[usr_cert] +basicConstraints=CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +subjectKeyIdentifier = hash + +[usr_cert_ke] +basicConstraints=CA:FALSE +keyUsage = nonRepudiation, keyEncipherment +subjectKeyIdentifier = hash + +[proxy_cert] +basicConstraints=CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +subjectKeyIdentifier = hash +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:0,policy:text:foo + +[pkinitc_principals] +princ1 = GeneralString:bar + +[pkinitc_principal_seq] +name_type = EXP:0,INTEGER:1 +name_string = EXP:1,SEQUENCE:pkinitc_principals + +[pkinitc_princ_name] +realm = EXP:0,GeneralString:TEST.H5L.SE +principal_name = EXP:1,SEQUENCE:pkinitc_principal_seq + +[pkinit_client_cert] +basicConstraints=CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +subjectKeyIdentifier = hash +subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:pkinitc_princ_name + +[https_cert] +basicConstraints=CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#extendedKeyUsage = https-server XXX +subjectKeyIdentifier = hash + +[pkinit_kdc_cert] +basicConstraints=CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = 1.3.6.1.5.2.3.5 +subjectKeyIdentifier = hash +subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:pkinitkdc_princ_name + +[pkinitkdc_princ_name] +realm = EXP:0,GeneralString:TEST.H5L.SE +principal_name = EXP:1,SEQUENCE:pkinitkdc_principal_seq + +[pkinitkdc_principal_seq] +name_type = EXP:0,INTEGER:1 +name_string = EXP:1,SEQUENCE:pkinitkdc_principals + +[pkinitkdc_principals] +princ1 = GeneralString:krbtgt +princ2 = GeneralString:TEST.H5L.SE + +[proxy10_cert] +basicConstraints=CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +subjectKeyIdentifier = hash +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:10,policy:text:foo + +[usr_cert_ds] +basicConstraints=CA:FALSE +keyUsage = nonRepudiation, digitalSignature +subjectKeyIdentifier = hash + +[ocsp_cert] +basicConstraints=CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +# ocsp-nocheck and kp-OCSPSigning +extendedKeyUsage = 1.3.6.1.5.5.7.48.1.5, 1.3.6.1.5.5.7.3.9 +subjectKeyIdentifier = hash + +[req_distinguished_name] +countryName = Country Name (2 letter code) +countryName_default = SE +countryName_min = 2 +countryName_max = 2 + +organizationalName = Organizational Unit Name (eg, section) + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +#[req_attributes] +#challengePassword = A challenge password +#challengePassword_min = 4 +#challengePassword_max = 20 + +[policy_match] +countryName = match +commonName = supplied diff --git a/third_party/heimdal/lib/hx509/data/pkinit-ec.crt b/third_party/heimdal/lib/hx509/data/pkinit-ec.crt new file mode 100644 index 0000000..54435d3 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/pkinit-ec.crt @@ -0,0 +1,81 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7 (0x7) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Mar 22 22:25:06 2019 GMT + Not After : Nov 21 22:25:06 2518 GMT + Subject: C=SE, CN=pkinit-ec + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:c0:2b:8e:f3:0c:c3:1b:88:94:eb:4e:6a:12:f2: + fb:63:99:77:a2:13:7a:16:ce:48:dc:48:9a:83:91: + 5e:a9:b8:ab:17:77:94:ae:55:09:8d:69:4a:a4:a8: + 6b:77:12:01:fb:3c:6f:cd:b1:e3:02:be:63:b1:43: + 8d:8f:df:8c:75 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 77:9B:74:4B:75:90:50:CE:20:C3:00:9B:A5:23:F7:69:A8:C7:CC:34 + X509v3 Subject Alternative Name: + othername:<unsupported> + Signature Algorithm: sha1WithRSAEncryption + 70:02:b8:13:0f:d9:2b:7a:e9:42:5c:82:6a:9d:ea:f8:51:dc: + a9:2e:67:ec:c3:cb:67:48:fe:6a:bd:58:86:67:c2:1f:d4:a0: + dc:7d:17:41:93:8d:e0:67:60:01:60:cc:34:1f:0e:b0:fc:9b: + 5f:f6:cf:91:2b:a3:ec:28:5b:80:ff:31:21:14:5b:3c:a2:5c: + 6b:3b:32:94:de:ab:03:d9:41:70:c1:4f:4e:49:4d:63:8f:9a: + 8b:be:14:87:b0:df:bc:64:83:e1:99:ce:e6:77:12:5a:43:e3: + 3b:d7:e9:10:5e:68:36:38:de:88:c2:78:af:97:a3:a2:4e:bf: + a9:2d:e1:98:f4:9a:35:ec:b4:2a:70:18:09:99:ff:80:fb:73: + 49:75:47:54:31:7a:e1:43:28:4b:53:71:81:92:4c:42:db:9b: + 52:38:ad:90:47:db:4e:da:75:6f:37:14:ce:56:6e:06:d0:40: + 8e:df:f1:71:23:98:ee:b4:43:b7:77:3a:1c:a5:a3:6f:3e:d3: + 5f:86:0b:6d:d4:b8:4a:2e:8a:e0:d7:d2:75:5f:ca:bc:9c:e2: + d8:b9:04:bf:ec:8a:1e:78:28:f5:13:73:9c:dd:2c:10:73:55: + cf:40:96:8d:8a:b4:1c:79:bd:aa:01:de:b2:de:c4:30:04:11: + af:d5:fb:cb:28:44:25:02:ab:b3:68:22:02:1b:99:b1:96:eb: + f7:f3:ad:6e:32:76:67:be:bb:78:bc:46:9a:1c:b3:8e:66:39: + eb:cb:d8:76:c8:06:e5:79:1e:f0:fa:54:3f:a1:ea:ff:60:e8: + fb:55:d9:1c:47:3a:e7:67:df:c8:69:1d:d1:9a:56:96:2b:01: + 79:ad:22:f2:7a:3b:e6:be:32:84:9a:e3:50:db:89:69:c1:3e: + 19:09:d5:b3:3c:2c:08:90:8b:93:aa:39:ae:48:90:ec:cf:79: + 3d:15:91:86:3e:38:0e:0a:99:b1:d9:78:14:59:17:44:c0:76: + 70:a0:7a:92:64:2a:60:04:aa:ce:6b:b1:d5:c1:3b:e8:1b:58: + 6f:7d:dd:dc:90:49:55:e1:37:5a:7b:75:89:da:08:c1:a5:33: + c9:f9:0d:4a:1d:08:e0:a8:be:3f:0e:a2:e0:10:71:92:50:f8: + 75:33:98:7c:be:c9:2f:c8:7c:b2:19:94:14:59:0b:1c:ca:bc: + 34:ff:03:a4:3c:f0:bd:ac:c8:f6:63:8f:59:d3:eb:65:e9:96: + 9b:21:a9:94:a7:7d:fe:dd:62:cd:77:62:6a:58:38:de:63:4c: + 0c:c3:ea:09:4f:6a:80:76:07:59:ba:15:d2:b4:c1:46:1e:11: + 50:5b:be:8d:8e:21:4e:78 +-----BEGIN CERTIFICATE----- +MIIDcDCCAVigAwIBAgIBBzANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMCAXDTE5MDMyMjIyMjUwNloYDzI1 +MTgxMTIxMjIyNTA2WjAhMQswCQYDVQQGEwJTRTESMBAGA1UEAwwJcGtpbml0LWVj +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEwCuO8wzDG4iU605qEvL7Y5l3ohN6 +Fs5I3Eiag5FeqbirF3eUrlUJjWlKpKhrdxIB+zxvzbHjAr5jsUONj9+MdaNzMHEw +CQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFHebdEt1kFDOIMMAm6Uj +92mox8w0MDgGA1UdEQQxMC+gLQYGKwYBBQICoCMwIaANGwtURVNULkg1TC5TRaEQ +MA6gAwIBAaEHMAUbA2JhcjANBgkqhkiG9w0BAQUFAAOCAgEAcAK4Ew/ZK3rpQlyC +ap3q+FHcqS5n7MPLZ0j+ar1YhmfCH9Sg3H0XQZON4GdgAWDMNB8OsPybX/bPkSuj +7ChbgP8xIRRbPKJcazsylN6rA9lBcMFPTklNY4+ai74Uh7DfvGSD4ZnO5ncSWkPj +O9fpEF5oNjjeiMJ4r5ejok6/qS3hmPSaNey0KnAYCZn/gPtzSXVHVDF64UMoS1Nx +gZJMQtubUjitkEfbTtp1bzcUzlZuBtBAjt/xcSOY7rRDt3c6HKWjbz7TX4YLbdS4 +Si6K4NfSdV/KvJzi2LkEv+yKHngo9RNznN0sEHNVz0CWjYq0HHm9qgHest7EMAQR +r9X7yyhEJQKrs2giAhuZsZbr9/OtbjJ2Z767eLxGmhyzjmY568vYdsgG5Xke8PpU +P6Hq/2Do+1XZHEc652ffyGkd0ZpWlisBea0i8no75r4yhJrjUNuJacE+GQnVszws +CJCLk6o5rkiQ7M95PRWRhj44DgqZsdl4FFkXRMB2cKB6kmQqYASqzmux1cE76BtY +b33d3JBJVeE3Wnt1idoIwaUzyfkNSh0I4Ki+Pw6i4BBxklD4dTOYfL7JL8h8shmU +FFkLHMq8NP8DpDzwvazI9mOPWdPrZemWmyGplKd9/t1izXdialg43mNMDMPqCU9q +gHYHWboV0rTBRh4RUFu+jY4hTng= +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/pkinit-ec.key b/third_party/heimdal/lib/hx509/data/pkinit-ec.key new file mode 100644 index 0000000..0ac3fe4 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/pkinit-ec.key @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg38AlgS7f0d6rvR6u +mLJVGl/UF04RYiIeWsVJYUNS7RKhRANCAATAK47zDMMbiJTrTmoS8vtjmXeiE3oW +zkjcSJqDkV6puKsXd5SuVQmNaUqkqGt3EgH7PG/NseMCvmOxQ42P34x1 +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/pkinit-proxy-chain.crt b/third_party/heimdal/lib/hx509/data/pkinit-proxy-chain.crt new file mode 100644 index 0000000..2b425bc --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/pkinit-proxy-chain.crt @@ -0,0 +1,149 @@ +-----BEGIN CERTIFICATE----- +MIIFODCCAyCgAwIBAgIJAJd7zCsMMPvAMA0GCSqGSIb3DQEBCwUAMB4xCzAJBgNV +BAYTAlNFMQ8wDQYDVQQDDAZwa2luaXQwIBcNMTkwMzIyMjIyNTA3WhgPMjUxODEx +MjEyMjI1MDdaMDUxCzAJBgNVBAYTAlNFMQ8wDQYDVQQDDAZwa2luaXQxFTATBgNV +BAMMDHBraW5pdC1wcm94eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +AM1Z218qhKJXqYoQ/5DZgDYNtgJ9QLkPF0vsu6cScVhykomP1H2Qjj3+u6ZFB9oj +YS/ynPgkCjwexA7nDGVxfrR0OksDNFGHwCu/O1wagzyeImgvYYzPlKyFqT+0IN0U +TgEoMdtXUduxmJGr0wEr2aMeiETUGZmRc02icTPZIznhf9elXmAp7EQspjtN9P04 +OCkVygr/FKkeI7XsZR8Ekzqdaf400g1Cy+X2kMvnRs/Tyf3qp/xv1RG7cDz+vfiB +8S/Vd2zSyBFboOZZi0xVo2vEs9nzBbmTQFAFINSEtIjJWb9Tupz4YwU/xK9bq2G7 +/eOrt4e9pXry1gUKNN/qZIEkbaebhWxW6twMVO/nyXlnklpF1PvPKHsWP2JqhJK7 +9SZcqZkeRit1wlwXsWhb+Zzl27K74P1WgNQF9lbPwhQ6bPmadirCs0kkMBDjmh4U +SJe/5wIOLVPY0KrhQeC7Vn+hkCxqRTwZQuLKDWUKgd4jmvsjfLYAZVQfGUBX1x7D +Wng44pW7ytOSbn/4pAu38FGGLbPcKNw+cRRtHtBpWiCthDIJ6gOmJo8JngaU2Iss +ozmxfGZsdQscUEFVwL5X9YaBpWcGKKxZH7UXq3S3wOEm2yQ6/UrdJnuP+xIYFEiA +c7tQIFBYoX11+/cZGyVZmn8ESM4ytw9QqmxxaDAEdaJjAgMBAAGjYDBeMAkGA1Ud +EwQCMAAwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBSU/W8lX964Gjrb5YqSo3zg3XLl +vzAlBggrBgEFBQcBDgEB/wQWMBQCAQAwDwYIKwYBBQUHFQAEA2ZvbzANBgkqhkiG +9w0BAQsFAAOCAgEA2bcpIO8UZ7eDFPtIZd6BWVrQZ5Dj+LZA0KV2v+FjoZQN0/w6 +gzloDy0x3yym6lOtCNPnjxcYP2yfGl5WZet1VXCR+KXXHGID2MkOXhXTCH7eSCGC +GZpOsSEWs+CXyP/X5B85nkweK8MzLRdJc4Ilxf1UMMOdobgQnRq41NgWyQxA8xLR +jEeGV+CD5dvteyqBeXvq4IBBUTqAiyoH57XXZRPwWH7z3h9f7B4GdoQuRBQK+idM +hLgtQ9nkT+DDyoMC6iAtIVwntxsAIg5rUSkQ6RgS3ap6SC94+v3q5V2BJaJl/R+0 +X5ybK2hRKWsUAvU280UX/xT5EGeokHwegI+F7yQflTGI1p090uhBYZvWYj2G8wf5 +nlE7a2h8IG3SmS7qUlKe+RyPwHce+jgHU0aS3ROxreLGf/VX1k3yR2Vk0wpVWFis +WeC7U5g+iqv/UomqxpFwP3iH8RJhL3eGYVmatHIXjm838wepofexqUL4UKoY/t+h +FmMusCz2SFZFbgOHF1Vd9C3c/mr6J4HbYju1hO09iOFuQmoo4CjNjdKyLvP1HSap +g7IPdLP0f++1gGcRq8AkFC9U/vZx5OPwjIku645WeOBoLhFcSoLxyhMeekSNXpwS +WHArnvVC7cmuvuzmzf5+XqmBzSD0RWGK09drTZdryXuzv8djbeqldeRr1Zg= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 6 (0x6) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Mar 22 22:25:06 2019 GMT + Not After : Nov 21 22:25:06 2518 GMT + Subject: C=SE, CN=pkinit + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:e4:e6:1a:b1:de:91:30:34:8a:c7:f2:d9:0a:09: + 82:13:46:e9:db:c8:54:1e:0e:b0:b0:0a:e3:a3:b5: + 55:3c:6f:f8:45:8f:24:ed:56:c5:16:23:aa:ad:86: + 5a:5a:e0:8f:a2:f5:82:59:cc:70:b7:45:cc:1b:44: + a7:49:4b:ff:63:28:9d:01:22:79:ca:1a:6a:2b:75: + f8:40:c0:f0:93:b1:ab:85:cd:af:88:ac:30:f3:cb: + 42:87:fc:be:76:bb:fd:1c:a4:45:7a:66:37:47:ea: + aa:bf:c4:4b:47:fb:5b:ab:3f:c1:22:a9:06:f2:61: + 3d:5b:20:51:fc:ce:a7:82:74:6f:3d:ac:68:d6:78: + a2:77:83:26:af:23:63:20:3f:21:6e:29:1f:55:4c: + a6:d0:5a:51:e5:96:c1:cd:22:03:22:ee:de:42:3c: + 82:4d:29:20:c6:be:85:5b:04:3a:5f:8b:c7:e8:4e: + aa:3c:8e:dd:0d:d8:e5:d0:ff:0b:52:37:40:51:0d: + 33:f7:a8:05:07:76:dc:48:20:cd:52:38:a4:1f:44: + 11:cf:6d:58:a9:5a:9a:34:cb:93:07:30:e3:66:7b: + dc:d3:0b:6b:a2:1c:3f:19:ec:0b:0c:ea:29:6c:75: + 4d:7a:86:cf:35:87:9e:50:15:f3:34:73:0e:ac:4b: + a5:aa:1f:a2:f9:d5:8f:34:bd:5f:19:ae:22:8c:7f: + f7:ca:64:e6:ed:42:75:e5:92:9c:53:53:b7:66:68: + e5:07:eb:08:40:ec:bd:7c:ae:b0:c4:a5:4b:d7:4b: + 58:86:05:a8:91:db:ee:7a:3f:c4:fd:83:e5:7b:cb: + d0:8c:87:68:3b:83:67:e5:6a:5e:fa:28:b5:ee:07: + b1:0d:6a:93:1e:b0:c7:5c:57:fd:ce:e2:9c:0f:5e: + fe:41:cf:20:f2:1d:88:52:00:d4:83:fe:5b:d7:87: + 49:b0:78:2b:a7:60:c2:55:c6:c3:a2:6d:16:04:7f: + 8b:12:f7:65:c6:91:41:53:d8:ac:70:c0:3d:83:d8: + e0:6c:bb:3e:48:b8:c2:72:be:c0:35:61:40:ff:9f: + 97:18:9e:c7:39:0f:93:36:8f:0e:a6:3c:6d:5b:fd: + 89:6a:bb:ee:5e:43:f8:0d:29:7a:cf:23:bf:0b:c1: + 29:76:ae:a2:9a:73:b2:d0:b9:bd:48:51:25:8a:6b: + a9:c5:07:94:26:03:10:74:7b:fc:b7:5d:8f:2d:97: + 55:11:3e:7c:04:89:0e:b9:b9:73:2a:6c:5b:12:19: + 65:92:48:64:d5:4f:2c:79:3f:16:ad:65:97:21:db: + 3c:30:68:67:aa:42:14:86:59:57:b0:79:15:9e:a3: + 05:4f:33 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 7A:C6:DB:B8:D2:75:D1:8D:BB:72:AE:B5:25:6E:6F:8C:AF:63:3A:4D + X509v3 Subject Alternative Name: + othername:<unsupported> + Signature Algorithm: sha1WithRSAEncryption + 7f:5c:76:fd:3d:ef:0c:7f:70:c7:09:d3:5c:c1:b6:40:25:47: + a3:6a:bf:4e:ad:d1:e6:cc:92:86:b6:6a:42:3d:4f:bc:f1:6f: + fd:7e:22:52:9c:dc:a6:0b:71:98:80:44:cf:f1:91:bb:50:c8: + 15:cd:8c:d8:9c:7d:8d:69:61:1b:4c:66:40:77:44:45:33:9c: + 9a:04:01:a1:4b:82:3a:d7:39:97:27:90:a6:71:9a:b1:9c:ce: + 60:01:8b:a5:6f:39:a3:e1:75:de:3c:5c:61:66:a5:50:db:0f: + 4a:03:32:8d:dd:e5:b6:ab:6a:b2:53:6a:4c:c9:99:74:f7:f5: + 1e:a5:06:1a:d3:64:26:c5:77:f4:a6:40:1a:c4:7e:22:05:a6: + a5:25:f7:5d:74:a5:c9:86:c0:3a:88:2e:6e:0e:58:4f:e5:6e: + e9:2a:34:2a:1d:1d:a4:e4:74:f3:a5:e5:56:5d:5f:02:c4:eb: + c7:12:f2:55:6a:f1:6c:ec:6e:b8:c1:2d:aa:4a:7d:ed:91:c8: + 78:1b:b7:b9:37:17:32:ee:1b:b5:d9:5c:98:d2:cf:d8:c6:90: + a5:c9:f1:eb:8d:2c:d4:90:b2:8c:e5:53:9a:66:20:92:8b:a2: + 0c:8b:76:9b:5f:5b:39:77:69:67:a7:8c:de:10:57:85:45:a4: + 8f:85:3a:59:5f:fc:0c:70:de:1c:67:33:5e:9b:a5:21:3d:bd: + 2e:de:3e:c2:0d:cf:8f:52:43:92:01:cc:47:da:af:47:85:69: + 94:d3:9f:c9:d5:5d:50:ca:27:a5:bb:c0:53:12:e0:e8:3c:ed: + 0d:bd:47:97:af:be:b8:f9:0c:10:2a:79:21:3c:15:ef:c0:a5: + eb:33:38:93:5b:a3:de:1a:97:eb:c3:db:04:1f:e8:f4:23:10: + ff:2d:1e:9b:4e:1f:8e:27:7d:71:34:e2:be:74:a2:62:69:9a: + 83:7b:6e:9e:e4:a2:7c:84:82:ff:83:b3:cd:d2:0f:74:05:72: + b8:b0:45:23:b6:cd:04:25:2d:58:7f:92:ce:68:f9:ba:d0:9e: + a8:e1:f8:c0:86:0e:aa:ee:f9:af:ff:5c:bf:46:76:08:b1:83: + e7:66:8b:ca:1b:8f:f4:9f:6a:ac:71:4e:3a:d1:77:fd:97:81: + ff:0e:d0:d1:4a:7e:6d:94:e6:8c:e1:28:92:b1:68:83:5a:62: + 48:0d:26:ee:28:60:57:ff:52:b8:1e:8c:03:d8:fb:c1:6e:4f: + fd:7a:46:0b:0f:c8:05:ad:3a:a4:68:be:fd:30:62:ce:f2:0a: + b1:34:2c:95:e7:e2:91:ec:a3:c6:4e:2d:a5:fe:09:45:84:38: + 9c:d7:f4:0b:18:22:9d:df +-----BEGIN CERTIFICATE----- +MIIFODCCAyCgAwIBAgIBBjANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMCAXDTE5MDMyMjIyMjUwNloYDzI1 +MTgxMTIxMjIyNTA2WjAeMQswCQYDVQQGEwJTRTEPMA0GA1UEAwwGcGtpbml0MIIC +IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5OYasd6RMDSKx/LZCgmCE0bp +28hUHg6wsArjo7VVPG/4RY8k7VbFFiOqrYZaWuCPovWCWcxwt0XMG0SnSUv/Yyid +ASJ5yhpqK3X4QMDwk7Grhc2viKww88tCh/y+drv9HKRFemY3R+qqv8RLR/tbqz/B +IqkG8mE9WyBR/M6ngnRvPaxo1niid4MmryNjID8hbikfVUym0FpR5ZbBzSIDIu7e +QjyCTSkgxr6FWwQ6X4vH6E6qPI7dDdjl0P8LUjdAUQ0z96gFB3bcSCDNUjikH0QR +z21YqVqaNMuTBzDjZnvc0wtrohw/GewLDOopbHVNeobPNYeeUBXzNHMOrEulqh+i ++dWPNL1fGa4ijH/3ymTm7UJ15ZKcU1O3ZmjlB+sIQOy9fK6wxKVL10tYhgWokdvu +ej/E/YPle8vQjIdoO4Nn5Wpe+ii17gexDWqTHrDHXFf9zuKcD17+Qc8g8h2IUgDU +g/5b14dJsHgrp2DCVcbDom0WBH+LEvdlxpFBU9iscMA9g9jgbLs+SLjCcr7ANWFA +/5+XGJ7HOQ+TNo8OpjxtW/2JarvuXkP4DSl6zyO/C8Epdq6imnOy0Lm9SFElimup +xQeUJgMQdHv8t12PLZdVET58BIkOublzKmxbEhllkkhk1U8seT8WrWWXIds8MGhn +qkIUhllXsHkVnqMFTzMCAwEAAaNzMHEwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAw +HQYDVR0OBBYEFHrG27jSddGNu3KutSVub4yvYzpNMDgGA1UdEQQxMC+gLQYGKwYB +BQICoCMwIaANGwtURVNULkg1TC5TRaEQMA6gAwIBAaEHMAUbA2JhcjANBgkqhkiG +9w0BAQUFAAOCAgEAf1x2/T3vDH9wxwnTXMG2QCVHo2q/Tq3R5syShrZqQj1PvPFv +/X4iUpzcpgtxmIBEz/GRu1DIFc2M2Jx9jWlhG0xmQHdERTOcmgQBoUuCOtc5lyeQ +pnGasZzOYAGLpW85o+F13jxcYWalUNsPSgMyjd3ltqtqslNqTMmZdPf1HqUGGtNk +JsV39KZAGsR+IgWmpSX3XXSlyYbAOogubg5YT+Vu6So0Kh0dpOR086XlVl1fAsTr +xxLyVWrxbOxuuMEtqkp97ZHIeBu3uTcXMu4btdlcmNLP2MaQpcnx640s1JCyjOVT +mmYgkouiDIt2m19bOXdpZ6eM3hBXhUWkj4U6WV/8DHDeHGczXpulIT29Lt4+wg3P +j1JDkgHMR9qvR4VplNOfydVdUMonpbvAUxLg6DztDb1Hl6++uPkMECp5ITwV78Cl +6zM4k1uj3hqX68PbBB/o9CMQ/y0em04fjid9cTTivnSiYmmag3tunuSifISC/4Oz +zdIPdAVyuLBFI7bNBCUtWH+Szmj5utCeqOH4wIYOqu75r/9cv0Z2CLGD52aLyhuP +9J9qrHFOOtF3/ZeB/w7Q0Up+bZTmjOEokrFog1piSA0m7ihgV/9SuB6MA9j7wW5P +/XpGCw/IBa06pGi+/TBizvIKsTQslefikeyjxk4tpf4JRYQ4nNf0Cxgind8= +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/pkinit-proxy.crt b/third_party/heimdal/lib/hx509/data/pkinit-proxy.crt new file mode 100644 index 0000000..d92acdf --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/pkinit-proxy.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFODCCAyCgAwIBAgIJAJd7zCsMMPvAMA0GCSqGSIb3DQEBCwUAMB4xCzAJBgNV +BAYTAlNFMQ8wDQYDVQQDDAZwa2luaXQwIBcNMTkwMzIyMjIyNTA3WhgPMjUxODEx +MjEyMjI1MDdaMDUxCzAJBgNVBAYTAlNFMQ8wDQYDVQQDDAZwa2luaXQxFTATBgNV +BAMMDHBraW5pdC1wcm94eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +AM1Z218qhKJXqYoQ/5DZgDYNtgJ9QLkPF0vsu6cScVhykomP1H2Qjj3+u6ZFB9oj +YS/ynPgkCjwexA7nDGVxfrR0OksDNFGHwCu/O1wagzyeImgvYYzPlKyFqT+0IN0U +TgEoMdtXUduxmJGr0wEr2aMeiETUGZmRc02icTPZIznhf9elXmAp7EQspjtN9P04 +OCkVygr/FKkeI7XsZR8Ekzqdaf400g1Cy+X2kMvnRs/Tyf3qp/xv1RG7cDz+vfiB +8S/Vd2zSyBFboOZZi0xVo2vEs9nzBbmTQFAFINSEtIjJWb9Tupz4YwU/xK9bq2G7 +/eOrt4e9pXry1gUKNN/qZIEkbaebhWxW6twMVO/nyXlnklpF1PvPKHsWP2JqhJK7 +9SZcqZkeRit1wlwXsWhb+Zzl27K74P1WgNQF9lbPwhQ6bPmadirCs0kkMBDjmh4U +SJe/5wIOLVPY0KrhQeC7Vn+hkCxqRTwZQuLKDWUKgd4jmvsjfLYAZVQfGUBX1x7D +Wng44pW7ytOSbn/4pAu38FGGLbPcKNw+cRRtHtBpWiCthDIJ6gOmJo8JngaU2Iss +ozmxfGZsdQscUEFVwL5X9YaBpWcGKKxZH7UXq3S3wOEm2yQ6/UrdJnuP+xIYFEiA +c7tQIFBYoX11+/cZGyVZmn8ESM4ytw9QqmxxaDAEdaJjAgMBAAGjYDBeMAkGA1Ud +EwQCMAAwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBSU/W8lX964Gjrb5YqSo3zg3XLl +vzAlBggrBgEFBQcBDgEB/wQWMBQCAQAwDwYIKwYBBQUHFQAEA2ZvbzANBgkqhkiG +9w0BAQsFAAOCAgEA2bcpIO8UZ7eDFPtIZd6BWVrQZ5Dj+LZA0KV2v+FjoZQN0/w6 +gzloDy0x3yym6lOtCNPnjxcYP2yfGl5WZet1VXCR+KXXHGID2MkOXhXTCH7eSCGC +GZpOsSEWs+CXyP/X5B85nkweK8MzLRdJc4Ilxf1UMMOdobgQnRq41NgWyQxA8xLR +jEeGV+CD5dvteyqBeXvq4IBBUTqAiyoH57XXZRPwWH7z3h9f7B4GdoQuRBQK+idM +hLgtQ9nkT+DDyoMC6iAtIVwntxsAIg5rUSkQ6RgS3ap6SC94+v3q5V2BJaJl/R+0 +X5ybK2hRKWsUAvU280UX/xT5EGeokHwegI+F7yQflTGI1p090uhBYZvWYj2G8wf5 +nlE7a2h8IG3SmS7qUlKe+RyPwHce+jgHU0aS3ROxreLGf/VX1k3yR2Vk0wpVWFis +WeC7U5g+iqv/UomqxpFwP3iH8RJhL3eGYVmatHIXjm838wepofexqUL4UKoY/t+h +FmMusCz2SFZFbgOHF1Vd9C3c/mr6J4HbYju1hO09iOFuQmoo4CjNjdKyLvP1HSap +g7IPdLP0f++1gGcRq8AkFC9U/vZx5OPwjIku645WeOBoLhFcSoLxyhMeekSNXpwS +WHArnvVC7cmuvuzmzf5+XqmBzSD0RWGK09drTZdryXuzv8djbeqldeRr1Zg= +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/pkinit-proxy.key b/third_party/heimdal/lib/hx509/data/pkinit-proxy.key new file mode 100644 index 0000000..6ef1f81 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/pkinit-proxy.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +k2odOmvIh8CJ2ZSNtza8KPoCHxzIOQU= +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/pkinit-pw.key b/third_party/heimdal/lib/hx509/data/pkinit-pw.key new file mode 100644 index 0000000..3fef51f --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/pkinit-pw.key @@ -0,0 +1,54 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,0D7945ED368F10EDD0E5FB517DA6CEDD + +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 +-----END RSA PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/pkinit.crt b/third_party/heimdal/lib/hx509/data/pkinit.crt new file mode 100644 index 0000000..3f20629 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/pkinit.crt @@ -0,0 +1,119 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 6 (0x6) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Mar 22 22:25:06 2019 GMT + Not After : Nov 21 22:25:06 2518 GMT + Subject: C=SE, CN=pkinit + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:e4:e6:1a:b1:de:91:30:34:8a:c7:f2:d9:0a:09: + 82:13:46:e9:db:c8:54:1e:0e:b0:b0:0a:e3:a3:b5: + 55:3c:6f:f8:45:8f:24:ed:56:c5:16:23:aa:ad:86: + 5a:5a:e0:8f:a2:f5:82:59:cc:70:b7:45:cc:1b:44: + a7:49:4b:ff:63:28:9d:01:22:79:ca:1a:6a:2b:75: + f8:40:c0:f0:93:b1:ab:85:cd:af:88:ac:30:f3:cb: + 42:87:fc:be:76:bb:fd:1c:a4:45:7a:66:37:47:ea: + aa:bf:c4:4b:47:fb:5b:ab:3f:c1:22:a9:06:f2:61: + 3d:5b:20:51:fc:ce:a7:82:74:6f:3d:ac:68:d6:78: + a2:77:83:26:af:23:63:20:3f:21:6e:29:1f:55:4c: + a6:d0:5a:51:e5:96:c1:cd:22:03:22:ee:de:42:3c: + 82:4d:29:20:c6:be:85:5b:04:3a:5f:8b:c7:e8:4e: + aa:3c:8e:dd:0d:d8:e5:d0:ff:0b:52:37:40:51:0d: + 33:f7:a8:05:07:76:dc:48:20:cd:52:38:a4:1f:44: + 11:cf:6d:58:a9:5a:9a:34:cb:93:07:30:e3:66:7b: + dc:d3:0b:6b:a2:1c:3f:19:ec:0b:0c:ea:29:6c:75: + 4d:7a:86:cf:35:87:9e:50:15:f3:34:73:0e:ac:4b: + a5:aa:1f:a2:f9:d5:8f:34:bd:5f:19:ae:22:8c:7f: + f7:ca:64:e6:ed:42:75:e5:92:9c:53:53:b7:66:68: + e5:07:eb:08:40:ec:bd:7c:ae:b0:c4:a5:4b:d7:4b: + 58:86:05:a8:91:db:ee:7a:3f:c4:fd:83:e5:7b:cb: + d0:8c:87:68:3b:83:67:e5:6a:5e:fa:28:b5:ee:07: + b1:0d:6a:93:1e:b0:c7:5c:57:fd:ce:e2:9c:0f:5e: + fe:41:cf:20:f2:1d:88:52:00:d4:83:fe:5b:d7:87: + 49:b0:78:2b:a7:60:c2:55:c6:c3:a2:6d:16:04:7f: + 8b:12:f7:65:c6:91:41:53:d8:ac:70:c0:3d:83:d8: + e0:6c:bb:3e:48:b8:c2:72:be:c0:35:61:40:ff:9f: + 97:18:9e:c7:39:0f:93:36:8f:0e:a6:3c:6d:5b:fd: + 89:6a:bb:ee:5e:43:f8:0d:29:7a:cf:23:bf:0b:c1: + 29:76:ae:a2:9a:73:b2:d0:b9:bd:48:51:25:8a:6b: + a9:c5:07:94:26:03:10:74:7b:fc:b7:5d:8f:2d:97: + 55:11:3e:7c:04:89:0e:b9:b9:73:2a:6c:5b:12:19: + 65:92:48:64:d5:4f:2c:79:3f:16:ad:65:97:21:db: + 3c:30:68:67:aa:42:14:86:59:57:b0:79:15:9e:a3: + 05:4f:33 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 7A:C6:DB:B8:D2:75:D1:8D:BB:72:AE:B5:25:6E:6F:8C:AF:63:3A:4D + X509v3 Subject Alternative Name: + othername:<unsupported> + Signature Algorithm: sha1WithRSAEncryption + 7f:5c:76:fd:3d:ef:0c:7f:70:c7:09:d3:5c:c1:b6:40:25:47: + a3:6a:bf:4e:ad:d1:e6:cc:92:86:b6:6a:42:3d:4f:bc:f1:6f: + fd:7e:22:52:9c:dc:a6:0b:71:98:80:44:cf:f1:91:bb:50:c8: + 15:cd:8c:d8:9c:7d:8d:69:61:1b:4c:66:40:77:44:45:33:9c: + 9a:04:01:a1:4b:82:3a:d7:39:97:27:90:a6:71:9a:b1:9c:ce: + 60:01:8b:a5:6f:39:a3:e1:75:de:3c:5c:61:66:a5:50:db:0f: + 4a:03:32:8d:dd:e5:b6:ab:6a:b2:53:6a:4c:c9:99:74:f7:f5: + 1e:a5:06:1a:d3:64:26:c5:77:f4:a6:40:1a:c4:7e:22:05:a6: + a5:25:f7:5d:74:a5:c9:86:c0:3a:88:2e:6e:0e:58:4f:e5:6e: + e9:2a:34:2a:1d:1d:a4:e4:74:f3:a5:e5:56:5d:5f:02:c4:eb: + c7:12:f2:55:6a:f1:6c:ec:6e:b8:c1:2d:aa:4a:7d:ed:91:c8: + 78:1b:b7:b9:37:17:32:ee:1b:b5:d9:5c:98:d2:cf:d8:c6:90: + a5:c9:f1:eb:8d:2c:d4:90:b2:8c:e5:53:9a:66:20:92:8b:a2: + 0c:8b:76:9b:5f:5b:39:77:69:67:a7:8c:de:10:57:85:45:a4: + 8f:85:3a:59:5f:fc:0c:70:de:1c:67:33:5e:9b:a5:21:3d:bd: + 2e:de:3e:c2:0d:cf:8f:52:43:92:01:cc:47:da:af:47:85:69: + 94:d3:9f:c9:d5:5d:50:ca:27:a5:bb:c0:53:12:e0:e8:3c:ed: + 0d:bd:47:97:af:be:b8:f9:0c:10:2a:79:21:3c:15:ef:c0:a5: + eb:33:38:93:5b:a3:de:1a:97:eb:c3:db:04:1f:e8:f4:23:10: + ff:2d:1e:9b:4e:1f:8e:27:7d:71:34:e2:be:74:a2:62:69:9a: + 83:7b:6e:9e:e4:a2:7c:84:82:ff:83:b3:cd:d2:0f:74:05:72: + b8:b0:45:23:b6:cd:04:25:2d:58:7f:92:ce:68:f9:ba:d0:9e: + a8:e1:f8:c0:86:0e:aa:ee:f9:af:ff:5c:bf:46:76:08:b1:83: + e7:66:8b:ca:1b:8f:f4:9f:6a:ac:71:4e:3a:d1:77:fd:97:81: + ff:0e:d0:d1:4a:7e:6d:94:e6:8c:e1:28:92:b1:68:83:5a:62: + 48:0d:26:ee:28:60:57:ff:52:b8:1e:8c:03:d8:fb:c1:6e:4f: + fd:7a:46:0b:0f:c8:05:ad:3a:a4:68:be:fd:30:62:ce:f2:0a: + b1:34:2c:95:e7:e2:91:ec:a3:c6:4e:2d:a5:fe:09:45:84:38: + 9c:d7:f4:0b:18:22:9d:df +-----BEGIN CERTIFICATE----- +MIIFODCCAyCgAwIBAgIBBjANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMCAXDTE5MDMyMjIyMjUwNloYDzI1 +MTgxMTIxMjIyNTA2WjAeMQswCQYDVQQGEwJTRTEPMA0GA1UEAwwGcGtpbml0MIIC +IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5OYasd6RMDSKx/LZCgmCE0bp +28hUHg6wsArjo7VVPG/4RY8k7VbFFiOqrYZaWuCPovWCWcxwt0XMG0SnSUv/Yyid +ASJ5yhpqK3X4QMDwk7Grhc2viKww88tCh/y+drv9HKRFemY3R+qqv8RLR/tbqz/B +IqkG8mE9WyBR/M6ngnRvPaxo1niid4MmryNjID8hbikfVUym0FpR5ZbBzSIDIu7e +QjyCTSkgxr6FWwQ6X4vH6E6qPI7dDdjl0P8LUjdAUQ0z96gFB3bcSCDNUjikH0QR +z21YqVqaNMuTBzDjZnvc0wtrohw/GewLDOopbHVNeobPNYeeUBXzNHMOrEulqh+i ++dWPNL1fGa4ijH/3ymTm7UJ15ZKcU1O3ZmjlB+sIQOy9fK6wxKVL10tYhgWokdvu +ej/E/YPle8vQjIdoO4Nn5Wpe+ii17gexDWqTHrDHXFf9zuKcD17+Qc8g8h2IUgDU +g/5b14dJsHgrp2DCVcbDom0WBH+LEvdlxpFBU9iscMA9g9jgbLs+SLjCcr7ANWFA +/5+XGJ7HOQ+TNo8OpjxtW/2JarvuXkP4DSl6zyO/C8Epdq6imnOy0Lm9SFElimup +xQeUJgMQdHv8t12PLZdVET58BIkOublzKmxbEhllkkhk1U8seT8WrWWXIds8MGhn +qkIUhllXsHkVnqMFTzMCAwEAAaNzMHEwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAw +HQYDVR0OBBYEFHrG27jSddGNu3KutSVub4yvYzpNMDgGA1UdEQQxMC+gLQYGKwYB +BQICoCMwIaANGwtURVNULkg1TC5TRaEQMA6gAwIBAaEHMAUbA2JhcjANBgkqhkiG +9w0BAQUFAAOCAgEAf1x2/T3vDH9wxwnTXMG2QCVHo2q/Tq3R5syShrZqQj1PvPFv +/X4iUpzcpgtxmIBEz/GRu1DIFc2M2Jx9jWlhG0xmQHdERTOcmgQBoUuCOtc5lyeQ +pnGasZzOYAGLpW85o+F13jxcYWalUNsPSgMyjd3ltqtqslNqTMmZdPf1HqUGGtNk +JsV39KZAGsR+IgWmpSX3XXSlyYbAOogubg5YT+Vu6So0Kh0dpOR086XlVl1fAsTr +xxLyVWrxbOxuuMEtqkp97ZHIeBu3uTcXMu4btdlcmNLP2MaQpcnx640s1JCyjOVT +mmYgkouiDIt2m19bOXdpZ6eM3hBXhUWkj4U6WV/8DHDeHGczXpulIT29Lt4+wg3P +j1JDkgHMR9qvR4VplNOfydVdUMonpbvAUxLg6DztDb1Hl6++uPkMECp5ITwV78Cl +6zM4k1uj3hqX68PbBB/o9CMQ/y0em04fjid9cTTivnSiYmmag3tunuSifISC/4Oz +zdIPdAVyuLBFI7bNBCUtWH+Szmj5utCeqOH4wIYOqu75r/9cv0Z2CLGD52aLyhuP +9J9qrHFOOtF3/ZeB/w7Q0Up+bZTmjOEokrFog1piSA0m7ihgV/9SuB6MA9j7wW5P +/XpGCw/IBa06pGi+/TBizvIKsTQslefikeyjxk4tpf4JRYQ4nNf0Cxgind8= +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/pkinit.key b/third_party/heimdal/lib/hx509/data/pkinit.key new file mode 100644 index 0000000..ee1c842 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/pkinit.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +RGobyk3036+cucUBlLFJBboNBbUzUX7l +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/proxy-level-test.crt b/third_party/heimdal/lib/hx509/data/proxy-level-test.crt new file mode 100644 index 0000000..51422e9 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/proxy-level-test.crt @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFVzCCAz+gAwIBAgIJAOXO+qv/iXxCMA0GCSqGSIb3DQEBCwUAMDExCzAJBgNV +BAYTAlNFMRIwEAYDVQQDDAlUZXN0IGNlcnQxDjAMBgNVBAMMBXByb3h5MCAXDTE5 +MDMyMjIyMjUxM1oYDzI1MTgxMTIxMjIyNTEzWjBBMQswCQYDVQQGEwJTRTESMBAG +A1UEAwwJVGVzdCBjZXJ0MQ4wDAYDVQQDDAVwcm94eTEOMAwGA1UEAwwFY2hpbGQw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDPMfDYnc56LmPFqSovq3KU +JcBypPhCtrOiJ3vwLIumg+NDlsWdhG0EP8xwGnbikR5RNAi/PtCV8cGsbQ3+Fio8 +AFVQs956itoNEvzoL+mbyNpyRVr1ph9qJ/lO5mzdNfCQb++b73bkygUaNKJPpdL5 +VNEwdG6bEEw59+WWqATO1geUv//AeNPqLrKFDMg5HQzCjGXhwE99J156AQ4fw6lB +0Yubssk6AfHLKd+UKh8qRPdO1EYzgHRuSGW7olXUbiS3wmPe1/JYMEiILjGmvAaA +Y55qsxFxZlTEehO99WF6rOrP1lC3ddcBd0fXBvJTiQeQsHT29tiVlPMFolmnQMbO ++bzLUPSx9ukW2deirFViXnC7pb5Cv8ZIJ2jsZEG3D4JM5WqZ1ycrKAq49r284LbX +LZH0ZnKZyGJmOjsXqIwWJJthMSlb7l/TA4IdRePYlaYQNQqIYwsPv9o+wv3owUaV +1PePDbn3PY/LENshooIV1yqhbA/Kr4ayiYuTFLtugPcWwi8sAXFNC3t6x4+xTK3n +S0n30hvIWZGKes8Zz46E6ANAf+stiKWxhTROrfLNKvenKXc4iVETOzZkBhQPyhk5 +dM1aC9rylQnm30o8oVnNpn/z9rePdCDbBluHKcJE4xcX5QpU3qybO5W5A7dhxsjw +0iVfuheSt5AkE4ixHAy/6wIDAQABo2AwXjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF +4DAdBgNVHQ4EFgQUcMWBbIV1HXTcW9hfIFew2urXq5QwJQYIKwYBBQUHAQ4BAf8E +FjAUAgEAMA8GCCsGAQUFBxUABANmb28wDQYJKoZIhvcNAQELBQADggIBAGygvoGy +/aUbaxSh8v1ug6qHHDMuKAddD4qnTx/JKFyUbVDKOUsiu4kuwH5uoIMhhPd5XYBw +2gNjptKIK/o5CMGXQpAFV9cfd7h57bhBTBU5xPvdsTsXSRObkmESE07XF81Vmqbz +3+YvbhYy98mHszMnsBzG24pJYn+Xhv0KfUINV+BzZZPZmwTkZki8gnAYpSfA85d2 +o1SO2iP0kZPUOoTRDrvN6v7EHFxar8Prka2jpHBPRXUMANbGl/Iu8SvzukVDc6g2 +pEBa9vDPl2Tf44kct+hB7Q735xSfHF5PJaUt/kzVclFNNWyNRr99S1mM5IEnAzF3 +PpkWHOke/L1dvWJT7wBSPfwMtyQz7gIGdA6Oq5CkFxE259bb7XJxRwfQV12pB4p5 +ZYUDTpd1P3D+VHQzmGi+EcgKEgoydVp4ikQj7aDUQWzZ49st+xLf0suE6wmNNSd+ +4dSuAeHbV0rglwlo/LZ3UPCd8nzhGTC5t6L8vFcDkrC7RyaBR8X2OeTU8FLP02me +q1eMF8k89L6ar1etLfC2+PKRGhcohJjm1Yz7sTSIeT6SnSxZeoSGAkFFwy70in0m +9mJNpNGfBCr2DS+XncpvVcIIYjHmrKWYfbnxYcouh/PJqpKKp4JXceV0u1e2DlvQ +Cew9o2dZuv5HXMmm4xpp8gyrzCzfZuExPIZd +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/proxy-level-test.key b/third_party/heimdal/lib/hx509/data/proxy-level-test.key new file mode 100644 index 0000000..352bfa8 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/proxy-level-test.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +JKt/SLgrlhrJ0BbcNKAnbzOeBZGPpEJk +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/proxy-test.crt b/third_party/heimdal/lib/hx509/data/proxy-test.crt new file mode 100644 index 0000000..9f9cd57 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/proxy-test.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFNzCCAx+gAwIBAgIJAKQmPUkmhyKhMA0GCSqGSIb3DQEBCwUAMCExCzAJBgNV +BAYTAlNFMRIwEAYDVQQDDAlUZXN0IGNlcnQwIBcNMTkwMzIyMjIyNTEyWhgPMjUx +ODExMjEyMjI1MTJaMDExCzAJBgNVBAYTAlNFMRIwEAYDVQQDDAlUZXN0IGNlcnQx +DjAMBgNVBAMMBXByb3h5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA +mPssWfri3hoR0eHC6FCqD3arIBwD+XeYJXS2y1zA9UgijF3rLDtyubOpp/5Or6Q9 +cO7m4S+4xPquasRUS8A9rJZbxi3rvptVFD2DBmpEUNbIjlW2TdymVpAtD4uHKpOA +xeEtn6eXlhDiiJcrrqLds9cLGRG0XaPSeTwzOWqhtyEeMp3rvVQ/NeMfYsMF87m/ +txopxdJnpEoArfxxudLSQ0HrILLVV/VbQZEcoJXEMjhZg0Qnw5rHRV5dacLT1gmp +w2yRQID0rbcKk6b3ukRHXD9OWNt074afzQJmMx1MDlHv8IeFtksxEhhA9i612LTi +KaU5Ac11ZJ+ew2YnV3HU3roH6BHeGeWHDhxqfpV7DPXZsUVo18kgrY+w1E+lcntT +FfWzWXF6p7gIPQKBy/IG3FsdP9ugx4y54Jl2HsrBEOjA+x45TL80T0zA0FXuu6fo +oljNGUrQfPQiWJCnQmWkjIhbVo+aovSlBRnOSsAxr7H8Ry4jhF2eQG8TIDgPRGs3 +DSwIUJyQwoRvRpo01ZJ1akfUkJFzv519EuN/zfNVTO2KBGVXprkONCZVN6eVpDVb +rClN5iUqCimn4xhv2T7VhDKO6mjOMMR38kdLvsrtAWBpob7hDHr0zAXCwSwheVVM +fMkYHZEyVfsxS7/ooA+oLwbHewhV3zJQDK6zAgyi+jUCAwEAAaNgMF4wCQYDVR0T +BAIwADALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFFyuJ+5Hf8HzZNaew6ZLRnQubKRB +MCUGCCsGAQUFBwEOAQH/BBYwFAIBADAPBggrBgEFBQcVAAQDZm9vMA0GCSqGSIb3 +DQEBCwUAA4ICAQAqn4xPkjg5lR+wOQwxKyxfzjS2ycEW+8WLp+l5p7qHmv4JOSwO +/XFf+6sRSGiBwHAoOq3yJlU0NzEq+uLjEg20/MXQ1+R4N2AsWeD4wUxRkjoukmc+ +at4wza4SoJLzfv8rYtZRx7quXDq+tFgAHxZv/AB3tghCyjS9JiaAc2aA015XmAec +qZcLjWoDmIH4mgT+LuenPbS9Dus8mGbOiTsns+iVCMZKJOBU1KF1UUy+f+J3SGqX +nsHzfMiFqU8qA6sQ3mZy4yqPG0Yu7r6YfpV2HQPCLXy1VZ3BINf/9YINaUCe/NpQ +Md1Pd6Q3U8+QObyAxXVfmTRFGCDu+S0NlpEfZzPnRYxr0ZfwC3SKWMwVHugv9v3k +qkZAgB4T9u0TqBjuB9mWoyzYEqwRgFg0AjrtgWXPJ8MSnth3eSrJjcXhEqgq1NvJ +SZVPzYW9RKB7lAM/4cDmrGXB1Lq2g4b5R8H1wzBtjL+CGjCuly9uR5HvxCOPLzPm +btZTRQtdA96L490wcv4D3JHN9ro0cq4QB2m6XKr2wDDh3CEgQQmaTKufWR8zAL8R +5HYtKxt1dcz6w4FiLgq9g+ADZMwJpErmGgldX/NKMz4Rfy0qMCprIn6XgPWWlSC4 +BT/0EyLjDJhwap661H5sMkchCx4uywG6EvQBRf4bxpWQgxReSO1znefULQ== +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/proxy-test.key b/third_party/heimdal/lib/hx509/data/proxy-test.key new file mode 100644 index 0000000..fc303ea --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/proxy-test.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +2f09X6R0XLrRpaAyQD+H/2DVhYM4CV0= +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/proxy10-child-child-test.crt b/third_party/heimdal/lib/hx509/data/proxy10-child-child-test.crt new file mode 100644 index 0000000..a606da6 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/proxy10-child-child-test.crt @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFezCCA2OgAwIBAgIJAIZ6hp81I2P5MA0GCSqGSIb3DQEBCwUAMEMxCzAJBgNV +BAYTAlNFMRIwEAYDVQQDDAlUZXN0IGNlcnQxEDAOBgNVBAMMB3Byb3h5MTAxDjAM +BgNVBAMMBWNoaWxkMCAXDTE5MDMyMjIyMjUxNloYDzI1MTgxMTIxMjIyNTE2WjBT +MQswCQYDVQQGEwJTRTESMBAGA1UEAwwJVGVzdCBjZXJ0MRAwDgYDVQQDDAdwcm94 +eTEwMQ4wDAYDVQQDDAVjaGlsZDEOMAwGA1UEAwwFY2hpbGQwggIiMA0GCSqGSIb3 +DQEBAQUAA4ICDwAwggIKAoICAQDOIxKHoKGi1/5V21RKfDqag54mjcz/ye0NvVHq +QKXJ4I8EVZyP7fwtl4ElcZ0GyHhqetXsulqgzuoGns5eCAq9mMkX4+3/EXvy0lyz +rVa+K5ysq6rsUMg7LPpiWA6RM3YYahNedzk3gsRghJ8q0vbvpTzNZQ1A+IOY1kdX +AeqyBqUT6kLycPYzU/eL2WzVe6pTRt1p2LKckDjxCKJI1ocYhWrdFhbB9YduvEVp +IRTINGXGvTpk8ZwzvgUQk1BmeGc1qqnmY+/wEEfpu1OZD2+5rJWQ7pSyB1jnMBxq +mTc5jkrMkzJX9F5JleVY9+bKZcBGu34mmAa4vXfwQOnM2HXAvjw3DJGlZCuNKExs +Ji9RyZcbe1NZqlBkp9l79cnlqURV6HftFFTyBNloEaNdzi81rYiMlxEoHEHqjLvo +9HCNV90WDDHPxDG+iOKyY6OAZ/QtjGEAjizp1NYHYkvTG3PzVvqQCsNF4iWzksQY +3M0OgyDybskOxvUN0NzDrF7Zw0+SqBSnYGWokVoghzQHMQHEOv/gYvrdw4kGs5Db +RXPfiYKJSPlsFgi0zXpZgm8Br2GxEW6ZfADaK/eONC6FW2W4aL9oqC8XyV2kYi/v +69G+UeULhVELL4bsUf0moPELFpuwyShHqfQ4l5Us5m66zxc/I0ekz2N66mWv/WQ9 +LNJBBwIDAQABo2AwXjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAdBgNVHQ4EFgQU +W8uH0Ungtk49Eykz3IE+8z536hswJQYIKwYBBQUHAQ4BAf8EFjAUAgEKMA8GCCsG +AQUFBxUABANmb28wDQYJKoZIhvcNAQELBQADggIBAAJxESHv3qYUiqzpmWI13Bbe +v9UqS/Le+WmWosv7JfbBV/aL9T2FF0uw/sMojKxxs88wfipYAaf7Or92JBlaSyt0 +YMhmhW7+miLEoWqeKkRfBx0q5IHvtmQMpNjDxA9uTXJW0U6FIyhVxXRte/3x4owk +KUfq5P43ErPMEVipaM0ns2y4+d9WimFtUY/52l/NqH84pwgP/2JuNYtRaOZ5pjyO +//zSUpiDbyE1OCeBG2b+YqKwDnCdxdqj0pZps/1fLieBr89GbS4SEMlqRgqN6LxO +XHkfS3frkD87l32zTuQnhD8vxKU01Kr85t6CPL+FIUhjUCxG3Tll8Z+coxgZp8IX +bjpyJfEx9834UqA3EDKpcuh3vndvov0nXe5XnxpmYevuCpd5fIjnbAdimFMshni7 +WhW+9HzKGTAKqaGXqRyEsPybm6Psw6F60p5Kbr9X8/+WM8j3mReQI4n1yKfW25kR +HlqLPmwrJUOGDsf2NV0kYg/8Zd+D5uT02LUKQPh5gd/9X/vm/YNJfmLvkK9V0yI9 +5U6nxRe+kQDreWSpP0mS2Bl3o/mOKDwinn4zZLU3IStrvhoVEo9LeIuehsul8zpk +57x1zHsKwviywBdAeJOXglQRhGhy76+jcN6Ii5rx6Na7uSlTSQqyz23bXfK8BcJr +TpIzMZLfa2s8faTjnjAD +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/proxy10-child-child-test.key b/third_party/heimdal/lib/hx509/data/proxy10-child-child-test.key new file mode 100644 index 0000000..7a55601 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/proxy10-child-child-test.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +9MZTi7RGridSLpg1QpqCUOcbhOQ1MKQ= +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/proxy10-child-test.crt b/third_party/heimdal/lib/hx509/data/proxy10-child-test.crt new file mode 100644 index 0000000..41cb814 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/proxy10-child-test.crt @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFWzCCA0OgAwIBAgIJAM764JrT/2XxMA0GCSqGSIb3DQEBCwUAMDMxCzAJBgNV +BAYTAlNFMRIwEAYDVQQDDAlUZXN0IGNlcnQxEDAOBgNVBAMMB3Byb3h5MTAwIBcN +MTkwMzIyMjIyNTE1WhgPMjUxODExMjEyMjI1MTVaMEMxCzAJBgNVBAYTAlNFMRIw +EAYDVQQDDAlUZXN0IGNlcnQxEDAOBgNVBAMMB3Byb3h5MTAxDjAMBgNVBAMMBWNo +aWxkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAunD1wwgtFwDOISki +iVAOjL6Q5UHHTFfGMkeXoa6/awWWjRBZT3IdmQlxxXlIEafS9vBMHW4xvAVf2qmg +Y6IZUy4EGqdrzzzmf64E/QcRW6vGbqRQY+HBqYDum+se4s/XfCo7sSpTLbZexhoM +Uz22k3reKzT3xurXtbxF+GQcpb2HnESnTL2omtU2PgEZ8BwhjisEB3rHTtQFqBdF +1uKSvRDJtDlRSUbqgY+cYCFUMdIEtn4djesLdH7yt34i5kukN6RajXJjQTSQFGce +egHaMOcQ7phIv7j305RFJ6waCXBwTCsBoIPtE2wt9pfgFu8zbcWenXpaxR+en/n/ +2gU7LnK3Odiyh3d0/8a+79gWxXWbmXYV2oYVl9ZxSTqa+wvzYQNaw1BPyhGxd95S +ACJOw8XuZ16ZEqQArEH59A36NKdca3OYjAf82fOEfRdIHm/CD9SEv9NRQpgzfzBF +cmiaIdBJg+QJJ0eNr4wZq8sVp1BKlnDosEq0nJ2ywRB3SeTbUrz3VxR3pzjtNYO1 +fIXUnBsoymZtUYqKiNLVP96RyWplxF204zEMP3zx0vIx6pKMmsWivEURxNdo/Hih +eiDaHB93aw+5+2pgKQOfIg0jj4ChE1JN2FOKBDAFq5+9rJIDuhS0Nk4PtYy/7n4R +iIDKiqWDNc2syEZYlEO+1QQuuRkCAwEAAaNgMF4wCQYDVR0TBAIwADALBgNVHQ8E +BAMCBeAwHQYDVR0OBBYEFD4E+/XklnqAWUXZrJa01AuHb6IbMCUGCCsGAQUFBwEO +AQH/BBYwFAIBCjAPBggrBgEFBQcVAAQDZm9vMA0GCSqGSIb3DQEBCwUAA4ICAQCW +nwXJetxx3Y82aBcyG9sQ5CTObsP1TyHRLVOKeA5jTwVxzSjQOChuUijLFbJ3QYds +vP8h56rjn/hLSi7kdyh1s1+mDBRFWAdJCfRfQhQWvgK7eaphln7qUXUXa3JR66Um +R56cXa6A4KG/Qk2vKw+NLjwA01vF+YzynSijwlaRptYLeOZMUMRzD8IwgqkdOAHr +6+RgiRrRIfdZHYmMX3/7sTvzub/d4QfANjKYPVkciW3E71yeAOLOfjjK68u4OMhn +F3I1vHdhCwxh87gZdiutmUjd+xTHhyIVObpSYIfSDCWqjp70s6sTJBdTCDnzIzcp +ta/iI1EkyOH0aOSzz4bclcWAA2R95JeQDP8PLUA8gddvkbW4f9RJbWMjAk3r6WMM +aSlx7djzbKdXIPd7ecFRWPf5uianNHlTHH2pZkHQoENCfuNTs688OzjBEDzUIvOZ +S3WbVlqSzdf8Xp8xDp01QbC/bwFJwOeZjdj4IVyF2vXB2AaE5Xy/umQz1NVnIqK1 +CUyv/EP4HMbWIW5hpaMZJ4VyhrkoX4sLDj25UN1VAzD9lTyAGpMv5KpWd98MhYIX +7KHP69Xo4CHf1RibdRVX6jW+GvzRZGHPb8/V8qgDwOM7UPjsPuwq5Cacatu0L7tQ +hqtYGxcBDAIRIrmm5sZCW4F3l4efUtzozWZS0vzTyQ== +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/proxy10-child-test.key b/third_party/heimdal/lib/hx509/data/proxy10-child-test.key new file mode 100644 index 0000000..7bc4a02 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/proxy10-child-test.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +Qshwvh4gXup0rcomkC+d8vVJ2p35 +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/proxy10-test.crt b/third_party/heimdal/lib/hx509/data/proxy10-test.crt new file mode 100644 index 0000000..9c89f71 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/proxy10-test.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFOTCCAyGgAwIBAgIJAKQmPUkmhyKjMA0GCSqGSIb3DQEBCwUAMCExCzAJBgNV +BAYTAlNFMRIwEAYDVQQDDAlUZXN0IGNlcnQwIBcNMTkwMzIyMjIyNTE0WhgPMjUx +ODExMjEyMjI1MTRaMDMxCzAJBgNVBAYTAlNFMRIwEAYDVQQDDAlUZXN0IGNlcnQx +EDAOBgNVBAMMB3Byb3h5MTAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQDNg69jn3h/uqasiOdUD/MC0vJoty8ncj9NNGfU7YHSLpRnuoyPL8YCRRbxreUP +lIQ5oAP4ERJSrrRoGWuwiboLthVj6OgM1IrU3h9M2sM7fGdLuQ1QCDP0Bsu23MPJ +KWMCUpd3p7jXrPaf1WzUtaIql0pjFFlqZRf1RLKvH4CfDgrx/k3z49RsiZtgxlw2 +VxpGL3cPUO1MfXEq4roMWdT0sGTdJ56l+PkF3Ud2DxhNytmDv1ld2gZhC5H+k5ZI +i3Xr8zvV2dCbSlnnXk8qTG+aWwYGpHFQPwP7UxQDUAk1XAX5/EBXwCTtTDNIhsNI +qB6k9MF3/mreD5frofvx6xEW8CShdAf2vUXC4OB8hkO/NfdaoQj99PL7d8LiICoQ +u4fOZ20g6zpkS+jir5p3KcVbotN0cMkx+k2YwyK3PoLV74RTsigOjp828eoT24Wz +3/ztjn4C0uMHcJz4yHmbrn7xOf7VcaNvfm9qz9H/MpA2Eg0Nj4nBOnTf25WLvgAB +KN0Ctb6rNbF3UfVR9h+QK4kQqhlwjMfPqeT2AL0fOFptotcdPj86z2ux1cvC/w/x +nZrgUdcj2GLLwvCxsmVx5RWOWU7wFoo3WrWpyx228CvaPTQXN5LKBIgpf1wmk4b1 +wR3afu0I5RQp8kSD/2kQBW24D4+AAH1jFbP9IfxxSXCazwIDAQABo2AwXjAJBgNV +HRMEAjAAMAsGA1UdDwQEAwIF4DAdBgNVHQ4EFgQUiFCNi8YSDjclAz4L6ZPKi9Ea +afQwJQYIKwYBBQUHAQ4BAf8EFjAUAgEKMA8GCCsGAQUFBxUABANmb28wDQYJKoZI +hvcNAQELBQADggIBAKEy0OrFQkrc3ngQXWBhOEoLElCYIpM5sVDn3aV8i8UAQ9KB +uLfxmcJm5CPZcIAFive2TWVFm1eq6Fr1WEwZ2QtAOXwoQwCzKISsdFRHEV2SNtpg +uUaKlhGUwiYWt9aPkmJD4f/VZB7LeKE4CWij88ey+76Lujkr+ILZnrXnc2Mwf3J/ +x+/RfINh4oM+7rHccAJtznwZ2TCBvF3p5cLlLH413IGnZjO/myz/EMQ8MJoFNc1G +dWXOZiGnbq2+W9rHKOV9rYhIZ5YLLiK6L7vKsLph83KTzWCZW7tZDAmwtFFXw406 +bdWL2+gWBC9SxN3RI2jB9VQtaLspOW+v8qH7cpDaO0xTXufsVjiGbh1hPdAMonQd +k0rrrkLY6ADguTYkHs1E3Eebki6LvyyXBEKJYTtEHfJnU2T1YWwFpqvvFOghFljH +QyZC29QR0rLB2B6uepQXl6d4fFYfYkhjx7SANDx4QA8QqrLgeGjufj9H3yk9e/XX +lto6sjNsOOncP9svCxJgQkp4w7tQxqZ/51RBQAJkUDkwPImstxTIFRdqeXHxLynX +3zTv6rt/767S7SlDfLZs8OrGKPeILGDBF/Q0UQrnrk9Oa+yP2QV3Msg79odKqBzK +MfcQ4DFIfnN9ZRq7d0ffaZ6AqJVbwYM/LlGFAC57z2xsuEAR+Ea0/bjzbaib +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/proxy10-test.key b/third_party/heimdal/lib/hx509/data/proxy10-test.key new file mode 100644 index 0000000..733c2ff --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/proxy10-test.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +M4C7UTY7JIl5vsDk5aoxq4Rt6pBkQQ== +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/revoke.crt b/third_party/heimdal/lib/hx509/data/revoke.crt new file mode 100644 index 0000000..ded2325 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/revoke.crt @@ -0,0 +1,116 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Mar 22 22:25:03 2019 GMT + Not After : Nov 21 22:25:03 2518 GMT + Subject: C=SE, CN=Revoke cert + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:ce:ac:a3:c6:69:47:c4:dd:f4:d9:0e:ac:42:90: + ae:57:f2:68:c4:77:89:9a:65:cd:8f:97:fc:68:6b: + 6b:65:0f:52:2d:d1:db:83:2c:1e:39:35:dd:fb:f6: + e8:c1:40:e9:ab:a6:48:23:e9:f0:e1:8f:72:27:6c: + e2:8d:04:e9:ca:e3:fe:ac:d9:28:16:be:db:19:fc: + 9a:20:d6:93:1f:15:b8:b6:97:cf:07:5a:da:ab:aa: + 97:c0:e9:39:7d:f9:df:96:c9:99:8f:6f:51:3f:64: + 13:0e:ad:0e:4e:2e:66:6f:72:6f:63:a6:a5:fd:85: + 0f:ac:ea:03:4d:81:14:bc:f3:5b:e5:fc:f6:6a:f7: + 57:b3:c3:b0:ed:4b:43:b1:cf:e2:1f:f6:44:07:83: + 27:b8:ef:19:9f:35:2b:95:59:b9:e1:69:c5:19:07: + 06:d7:17:da:35:4b:ba:74:68:c3:d3:28:ab:1e:b4: + 8a:ba:2b:f3:5e:06:75:0c:c8:a2:a9:ea:ec:29:1a: + 98:fb:b6:00:e0:98:78:cf:ea:36:2c:e1:51:8e:15: + 74:ba:4e:2d:8c:df:9b:72:72:52:b7:c7:82:45:35: + ba:c3:62:bf:29:d0:c0:17:6b:be:3b:e4:87:6a:26: + 34:4f:84:b5:ad:34:72:5f:4c:96:d8:d4:cd:5d:6f: + a3:ac:b1:55:a8:c8:c6:5d:99:0b:f0:bd:5e:f2:85: + 3e:74:05:d7:0f:9f:95:5a:14:1f:19:31:af:55:75: + 2a:80:22:7b:f7:ff:89:4b:70:5a:74:52:77:7a:ac: + 6b:86:2d:cc:5e:ca:57:3d:a1:20:d0:95:80:0b:48: + 26:52:69:9d:19:7f:0e:a9:63:97:70:b6:25:64:79: + ae:19:45:f8:7f:fd:23:75:9b:0f:d5:57:ae:56:50: + 9a:0c:fd:eb:f2:1b:a9:0a:3d:a2:1d:f3:07:cd:b9: + 63:5b:3d:95:21:9a:f6:27:2e:46:6a:3f:8f:48:b9: + e5:d7:ef:27:08:fc:45:37:70:23:88:a2:89:50:7e: + a3:ba:06:b3:b9:50:60:7d:aa:d6:eb:1c:b9:79:1c: + 16:06:d2:07:d3:c6:09:73:2a:8a:92:10:93:cc:52: + b4:bf:4b:09:d6:71:c1:60:57:3e:2f:12:13:90:18: + 06:44:cf:79:6f:50:78:11:8c:e9:ab:2b:97:19:5f: + b2:67:a9:fa:9b:b0:99:44:35:0e:00:18:6f:9a:00: + 39:e2:ac:e2:79:25:e1:46:d2:18:e4:80:d5:ca:ed: + 15:dc:7f:a7:90:7f:26:71:26:38:6b:ef:be:92:0c: + 07:64:24:64:a7:85:9d:2b:d9:14:bc:64:40:46:eb: + 78:b9:dd + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 3B:AC:F2:D9:72:19:FF:77:61:0C:6B:2C:C0:69:D0:28:46:8A:C1:D7 + Signature Algorithm: sha1WithRSAEncryption + 23:5d:75:da:82:54:6a:eb:29:cf:e0:55:da:4e:69:c3:d1:7b: + 27:20:37:ca:3e:ac:ba:55:30:0d:a6:57:44:de:1b:71:aa:57: + 80:8d:55:e1:48:fb:43:dc:23:d3:fd:85:ab:36:35:11:1d:41: + 30:59:ff:e4:61:e1:4d:14:8b:64:9e:cc:a0:71:19:a3:a9:10: + 84:47:72:dd:2b:56:5e:78:a9:ed:f1:32:8b:b4:5b:87:aa:bd: + 74:4f:ee:50:ba:36:d5:70:56:40:7d:64:d6:04:42:ae:50:2b: + 95:48:f5:74:8b:a6:b5:5c:49:9d:9c:f1:0c:0f:0a:f1:53:43: + ec:1f:59:6f:1e:54:ca:9d:b2:39:73:58:28:b7:0b:74:e3:ed: + d4:36:ef:7d:1d:c6:1f:2c:ff:a7:df:a2:a7:9e:94:b9:3f:3d: + 18:fa:07:d6:e9:03:f6:3a:d1:79:55:df:af:12:13:ef:45:af: + 63:57:fc:ef:db:5c:bd:e7:93:b5:81:35:e9:a9:e4:39:99:b9: + 32:7b:6f:1a:14:41:3a:fa:68:3c:0a:ae:9e:95:51:72:32:dc: + d6:e9:98:7d:65:db:ce:57:1f:1a:e5:2a:5a:c0:07:26:64:f0: + 49:ff:af:97:74:fe:98:20:94:7f:f7:3c:a7:46:ed:ad:e5:1b: + 7a:08:c4:d4:ce:3f:8a:ef:07:79:ec:d5:f1:1b:2b:f6:e0:95: + 31:ef:8e:bd:b8:ec:a7:84:f8:ff:c6:39:7a:15:8d:4b:4e:05: + c8:e6:2e:bb:bb:74:5a:51:92:f7:b1:04:55:2b:dc:42:18:d5: + 83:95:c4:d0:73:10:62:d5:55:8d:ea:a0:fd:ff:ef:10:9b:8f: + b3:ba:8a:91:75:5e:b9:9d:36:7d:53:5d:8d:1b:0d:c5:bb:1c: + 23:fc:08:5b:1f:3a:d5:1c:35:61:48:58:8e:c0:42:7c:3c:c8: + a0:17:8a:04:13:a6:03:49:cf:86:18:39:32:e4:fe:32:38:bd: + 53:bd:49:fa:65:63:3d:41:6a:c7:65:f5:df:7d:7b:8d:d0:74: + b2:c3:8b:bd:1e:4f:96:15:a0:7b:23:fe:81:e0:de:7f:06:b3: + f8:a2:52:cf:43:91:49:6f:ae:d8:6f:4f:51:85:7b:c2:f7:f8: + c8:4d:e0:a8:48:9a:5b:05:e2:60:fd:b7:bb:b7:7a:2b:35:e6: + 15:f3:e8:5f:b6:cb:d5:b0:7b:45:70:db:fe:82:97:c5:6b:be: + a9:60:21:87:19:b6:91:32:2f:01:b3:04:84:a3:1d:8b:06:00: + 3e:37:f4:c3:ff:b4:55:cb:cc:d1:d1:96:9b:d8:1a:0b:9f:47: + 66:b7:90:9c:d1:09:c2:aa +-----BEGIN CERTIFICATE----- +MIIFAzCCAuugAwIBAgIBAzANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMCAXDTE5MDMyMjIyMjUwM1oYDzI1 +MTgxMTIxMjIyNTAzWjAjMQswCQYDVQQGEwJTRTEUMBIGA1UEAwwLUmV2b2tlIGNl +cnQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDOrKPGaUfE3fTZDqxC +kK5X8mjEd4maZc2Pl/xoa2tlD1It0duDLB45Nd379ujBQOmrpkgj6fDhj3InbOKN +BOnK4/6s2SgWvtsZ/Jog1pMfFbi2l88HWtqrqpfA6Tl9+d+WyZmPb1E/ZBMOrQ5O +LmZvcm9jpqX9hQ+s6gNNgRS881vl/PZq91ezw7DtS0Oxz+If9kQHgye47xmfNSuV +WbnhacUZBwbXF9o1S7p0aMPTKKsetIq6K/NeBnUMyKKp6uwpGpj7tgDgmHjP6jYs +4VGOFXS6Ti2M35tyclK3x4JFNbrDYr8p0MAXa7475IdqJjRPhLWtNHJfTJbY1M1d +b6OssVWoyMZdmQvwvV7yhT50BdcPn5VaFB8ZMa9VdSqAInv3/4lLcFp0Und6rGuG +Lcxeylc9oSDQlYALSCZSaZ0Zfw6pY5dwtiVkea4ZRfh//SN1mw/VV65WUJoM/evy +G6kKPaId8wfNuWNbPZUhmvYnLkZqP49IueXX7ycI/EU3cCOIoolQfqO6BrO5UGB9 +qtbrHLl5HBYG0gfTxglzKoqSEJPMUrS/SwnWccFgVz4vEhOQGAZEz3lvUHgRjOmr +K5cZX7JnqfqbsJlENQ4AGG+aADnirOJ5JeFG0hjkgNXK7RXcf6eQfyZxJjhr776S +DAdkJGSnhZ0r2RS8ZEBG63i53QIDAQABozkwNzAJBgNVHRMEAjAAMAsGA1UdDwQE +AwIF4DAdBgNVHQ4EFgQUO6zy2XIZ/3dhDGsswGnQKEaKwdcwDQYJKoZIhvcNAQEF +BQADggIBACNdddqCVGrrKc/gVdpOacPReycgN8o+rLpVMA2mV0TeG3GqV4CNVeFI ++0PcI9P9has2NREdQTBZ/+Rh4U0Ui2SezKBxGaOpEIRHct0rVl54qe3xMou0W4eq +vXRP7lC6NtVwVkB9ZNYEQq5QK5VI9XSLprVcSZ2c8QwPCvFTQ+wfWW8eVMqdsjlz +WCi3C3Tj7dQ2730dxh8s/6ffoqeelLk/PRj6B9bpA/Y60XlV368SE+9Fr2NX/O/b +XL3nk7WBNemp5DmZuTJ7bxoUQTr6aDwKrp6VUXIy3NbpmH1l285XHxrlKlrAByZk +8En/r5d0/pgglH/3PKdG7a3lG3oIxNTOP4rvB3ns1fEbK/bglTHvjr247KeE+P/G +OXoVjUtOBcjmLru7dFpRkvexBFUr3EIY1YOVxNBzEGLVVY3qoP3/7xCbj7O6ipF1 +XrmdNn1TXY0bDcW7HCP8CFsfOtUcNWFIWI7AQnw8yKAXigQTpgNJz4YYOTLk/jI4 +vVO9SfplYz1Basdl9d99e43QdLLDi70eT5YVoHsj/oHg3n8Gs/iiUs9DkUlvrthv +T1GFe8L3+MhN4KhImlsF4mD9t7u3eis15hXz6F+2y9Wwe0Vw2/6Cl8VrvqlgIYcZ +tpEyLwGzBISjHYsGAD439MP/tFXLzNHRlpvYGgufR2a3kJzRCcKq +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/revoke.key b/third_party/heimdal/lib/hx509/data/revoke.key new file mode 100644 index 0000000..d70b74f --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/revoke.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +oSgi/Llzrh+HYp+WubHP32IPhXGX+w0= +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/secp256r1TestCA.cert.pem b/third_party/heimdal/lib/hx509/data/secp256r1TestCA.cert.pem new file mode 100644 index 0000000..3522b09 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/secp256r1TestCA.cert.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBuTCCAWCgAwIBAgIBATAKBggqhkjOPQQDAjA2MQswCQYDVQQGEwJTRTEQMA4G +A1UECgwHSGVpbWRhbDEVMBMGA1UEAwwMQ0Egc2VjcDI1NnIxMCAXDTE5MDMyMjIy +MjUyNVoYDzI1MTgxMTIxMjIyNTI1WjA2MQswCQYDVQQGEwJTRTEQMA4GA1UECgwH +SGVpbWRhbDEVMBMGA1UEAwwMQ0Egc2VjcDI1NnIxMFkwEwYHKoZIzj0CAQYIKoZI +zj0DAQcDQgAE5SuFK+KhglopQr1aMjl4ZEBaw4HYM2yVORyBOQWx3e8Pj90bFocE +4gyS4P2V0YraxACsQgMp+s4e8/6gXPeMtqNdMFswHQYDVR0OBBYEFOtR3wCoaF9m +8dWylzOdd5vfbwmDMB8GA1UdIwQYMBaAFOtR3wCoaF9m8dWylzOdd5vfbwmDMAwG +A1UdEwQFMAMBAf8wCwYDVR0PBAQDAgEGMAoGCCqGSM49BAMCA0cAMEQCIF/JTbEv +iuYcuREFzWgZ/AgfLe2sRwEgSy6UcAWOYllkAiApMzA3xKjaX1/hhkDGKZnHfcTM +tRuM0FuTdO+e15ku8w== +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/secp256r1TestCA.key.pem b/third_party/heimdal/lib/hx509/data/secp256r1TestCA.key.pem new file mode 100644 index 0000000..3888266 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/secp256r1TestCA.key.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgL2N0gdHhAjBGcJ40 +gHePPMwGKygIVDXTfjysn9zPiSOhRANCAATlK4Ur4qGCWilCvVoyOXhkQFrDgdgz +bJU5HIE5BbHd7w+P3RsWhwTiDJLg/ZXRitrEAKxCAyn6zh7z/qBc94y2 +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/secp256r1TestCA.pem b/third_party/heimdal/lib/hx509/data/secp256r1TestCA.pem new file mode 100644 index 0000000..9b1df2c --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/secp256r1TestCA.pem @@ -0,0 +1,17 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgL2N0gdHhAjBGcJ40 +gHePPMwGKygIVDXTfjysn9zPiSOhRANCAATlK4Ur4qGCWilCvVoyOXhkQFrDgdgz +bJU5HIE5BbHd7w+P3RsWhwTiDJLg/ZXRitrEAKxCAyn6zh7z/qBc94y2 +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIBuTCCAWCgAwIBAgIBATAKBggqhkjOPQQDAjA2MQswCQYDVQQGEwJTRTEQMA4G +A1UECgwHSGVpbWRhbDEVMBMGA1UEAwwMQ0Egc2VjcDI1NnIxMCAXDTE5MDMyMjIy +MjUyNVoYDzI1MTgxMTIxMjIyNTI1WjA2MQswCQYDVQQGEwJTRTEQMA4GA1UECgwH +SGVpbWRhbDEVMBMGA1UEAwwMQ0Egc2VjcDI1NnIxMFkwEwYHKoZIzj0CAQYIKoZI +zj0DAQcDQgAE5SuFK+KhglopQr1aMjl4ZEBaw4HYM2yVORyBOQWx3e8Pj90bFocE +4gyS4P2V0YraxACsQgMp+s4e8/6gXPeMtqNdMFswHQYDVR0OBBYEFOtR3wCoaF9m +8dWylzOdd5vfbwmDMB8GA1UdIwQYMBaAFOtR3wCoaF9m8dWylzOdd5vfbwmDMAwG +A1UdEwQFMAMBAf8wCwYDVR0PBAQDAgEGMAoGCCqGSM49BAMCA0cAMEQCIF/JTbEv +iuYcuREFzWgZ/AgfLe2sRwEgSy6UcAWOYllkAiApMzA3xKjaX1/hhkDGKZnHfcTM +tRuM0FuTdO+e15ku8w== +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/secp256r2TestClient.cert.pem b/third_party/heimdal/lib/hx509/data/secp256r2TestClient.cert.pem new file mode 100644 index 0000000..5763c5a --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/secp256r2TestClient.cert.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBsDCCAVegAwIBAgIBAjAKBggqhkjOPQQDAjA2MQswCQYDVQQGEwJTRTEQMA4G +A1UECgwHSGVpbWRhbDEVMBMGA1UEAwwMQ0Egc2VjcDI1NnIxMCAXDTE5MDMyMjIy +MjUyNVoYDzI1MTgxMTIxMjIyNTI1WjAwMQswCQYDVQQGEwJTRTEQMA4GA1UECgwH +SGVpbWRhbDEPMA0GA1UEAwwGQ2xpZW50MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD +QgAE7v8wIgEd/yBAtDmW2nW7II4IDDy7KVlnv6/+sHegoe4AjIvqr9CNldkfcVHl +VwjMA1q83lIB/H0IUmk+T6lQhKNaMFgwHQYDVR0OBBYEFKNeDhfd+znE5CBO6aNl +DAUjXdF6MB8GA1UdIwQYMBaAFOtR3wCoaF9m8dWylzOdd5vfbwmDMAkGA1UdEwQC +MAAwCwYDVR0PBAQDAgSwMAoGCCqGSM49BAMCA0cAMEQCIBVFIAeFxXeB4LURDxv/ +YnGzJJK0b+pjK5hVEPYww8dzAiAmHrccM21Ga7S+/yFWIvMe3BKtAl0O62TTI2Fg +CHiIWQ== +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/secp256r2TestClient.key.pem b/third_party/heimdal/lib/hx509/data/secp256r2TestClient.key.pem new file mode 100644 index 0000000..36c67f9 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/secp256r2TestClient.key.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg6oD5CbNzN7oAWqcq +dKJKw2WU5EwnUV05+7S9gXgeW/qhRANCAATu/zAiAR3/IEC0OZbadbsgjggMPLsp +WWe/r/6wd6Ch7gCMi+qv0I2V2R9xUeVXCMwDWrzeUgH8fQhSaT5PqVCE +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/secp256r2TestClient.pem b/third_party/heimdal/lib/hx509/data/secp256r2TestClient.pem new file mode 100644 index 0000000..9f49adc --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/secp256r2TestClient.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIIBsDCCAVegAwIBAgIBAjAKBggqhkjOPQQDAjA2MQswCQYDVQQGEwJTRTEQMA4G +A1UECgwHSGVpbWRhbDEVMBMGA1UEAwwMQ0Egc2VjcDI1NnIxMCAXDTE5MDMyMjIy +MjUyNVoYDzI1MTgxMTIxMjIyNTI1WjAwMQswCQYDVQQGEwJTRTEQMA4GA1UECgwH +SGVpbWRhbDEPMA0GA1UEAwwGQ2xpZW50MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD +QgAE7v8wIgEd/yBAtDmW2nW7II4IDDy7KVlnv6/+sHegoe4AjIvqr9CNldkfcVHl +VwjMA1q83lIB/H0IUmk+T6lQhKNaMFgwHQYDVR0OBBYEFKNeDhfd+znE5CBO6aNl +DAUjXdF6MB8GA1UdIwQYMBaAFOtR3wCoaF9m8dWylzOdd5vfbwmDMAkGA1UdEwQC +MAAwCwYDVR0PBAQDAgSwMAoGCCqGSM49BAMCA0cAMEQCIBVFIAeFxXeB4LURDxv/ +YnGzJJK0b+pjK5hVEPYww8dzAiAmHrccM21Ga7S+/yFWIvMe3BKtAl0O62TTI2Fg +CHiIWQ== +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg6oD5CbNzN7oAWqcq +dKJKw2WU5EwnUV05+7S9gXgeW/qhRANCAATu/zAiAR3/IEC0OZbadbsgjggMPLsp +WWe/r/6wd6Ch7gCMi+qv0I2V2R9xUeVXCMwDWrzeUgH8fQhSaT5PqVCE +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/secp256r2TestServer.cert.pem b/third_party/heimdal/lib/hx509/data/secp256r2TestServer.cert.pem new file mode 100644 index 0000000..71935b8 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/secp256r2TestServer.cert.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBsDCCAVegAwIBAgIBAjAKBggqhkjOPQQDAjA2MQswCQYDVQQGEwJTRTEQMA4G +A1UECgwHSGVpbWRhbDEVMBMGA1UEAwwMQ0Egc2VjcDI1NnIxMCAXDTE5MDMyMjIy +MjUyNVoYDzI1MTgxMTIxMjIyNTI1WjAwMQswCQYDVQQGEwJTRTEQMA4GA1UECgwH +SGVpbWRhbDEPMA0GA1UEAwwGU2VydmVyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD +QgAEi1mCfULxkG8qSQ2gSh9YvQksJNodPaUmPt32NG1IqJHY+U613keG14Oo/vwr +h6CVEyTmeqyYSihqV9s2wUHLxKNaMFgwHQYDVR0OBBYEFOowNM57NxGxrHqV/oT9 +eT5DM+iuMB8GA1UdIwQYMBaAFOtR3wCoaF9m8dWylzOdd5vfbwmDMAkGA1UdEwQC +MAAwCwYDVR0PBAQDAgSwMAoGCCqGSM49BAMCA0cAMEQCIB2nDbiSg6jTeoSWfCvG +23Pn4xxbes8Nb+/8+1lDjLWPAiA+KB8wJhUA4hO/Axfu85wKjddpbGtJR0JlxtEe +whF52Q== +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/secp256r2TestServer.key.pem b/third_party/heimdal/lib/hx509/data/secp256r2TestServer.key.pem new file mode 100644 index 0000000..fb57e79 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/secp256r2TestServer.key.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgKo/47DaveCl90GxH +LCE7IGBua2XsE+jI4RUWZrqjhBGhRANCAASLWYJ9QvGQbypJDaBKH1i9CSwk2h09 +pSY+3fY0bUiokdj5TrXeR4bXg6j+/CuHoJUTJOZ6rJhKKGpX2zbBQcvE +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/secp256r2TestServer.pem b/third_party/heimdal/lib/hx509/data/secp256r2TestServer.pem new file mode 100644 index 0000000..31a354d --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/secp256r2TestServer.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIIBsDCCAVegAwIBAgIBAjAKBggqhkjOPQQDAjA2MQswCQYDVQQGEwJTRTEQMA4G +A1UECgwHSGVpbWRhbDEVMBMGA1UEAwwMQ0Egc2VjcDI1NnIxMCAXDTE5MDMyMjIy +MjUyNVoYDzI1MTgxMTIxMjIyNTI1WjAwMQswCQYDVQQGEwJTRTEQMA4GA1UECgwH +SGVpbWRhbDEPMA0GA1UEAwwGU2VydmVyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD +QgAEi1mCfULxkG8qSQ2gSh9YvQksJNodPaUmPt32NG1IqJHY+U613keG14Oo/vwr +h6CVEyTmeqyYSihqV9s2wUHLxKNaMFgwHQYDVR0OBBYEFOowNM57NxGxrHqV/oT9 +eT5DM+iuMB8GA1UdIwQYMBaAFOtR3wCoaF9m8dWylzOdd5vfbwmDMAkGA1UdEwQC +MAAwCwYDVR0PBAQDAgSwMAoGCCqGSM49BAMCA0cAMEQCIB2nDbiSg6jTeoSWfCvG +23Pn4xxbes8Nb+/8+1lDjLWPAiA+KB8wJhUA4hO/Axfu85wKjddpbGtJR0JlxtEe +whF52Q== +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgKo/47DaveCl90GxH +LCE7IGBua2XsE+jI4RUWZrqjhBGhRANCAASLWYJ9QvGQbypJDaBKH1i9CSwk2h09 +pSY+3fY0bUiokdj5TrXeR4bXg6j+/CuHoJUTJOZ6rJhKKGpX2zbBQcvE +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/sf-class2-root.pem b/third_party/heimdal/lib/hx509/data/sf-class2-root.pem new file mode 100644 index 0000000..d552e65 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/sf-class2-root.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl +MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp +U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw +NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE +ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp +ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 +DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf +8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN ++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 +X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa +K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA +1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G +A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR +zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 +YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD +bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 +L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D +eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp +VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY +WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/static-file b/third_party/heimdal/lib/hx509/data/static-file new file mode 100644 index 0000000..2216857 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/static-file @@ -0,0 +1,84 @@ +This is a static file don't change the content, it is used in the test + +#!/bin/sh +# +# Copyright (c) 2005 Kungliga Tekniska Hgskolan +# (Royal Institute of Technology, Stockholm, Sweden). +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Institute nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# + +srcdir="@srcdir@" + +echo "try printing" +./hxtool print \ + --pass=PASS:foobar \ + PKCS12:$srcdir/data/test.p12 || exit 1 + +echo "make sure entry is found (friendlyname)" +./hxtool query \ + --pass=PASS:foobar \ + --friendlyname=friendlyname-test \ + PKCS12:$srcdir/data/test.p12 || exit 1 + +echo "make sure entry is not found (friendlyname)" +./hxtool query \ + --pass=PASS:foobar \ + --friendlyname=friendlyname-test-not \ + PKCS12:$srcdir/data/test.p12 && exit 1 + +echo "check for ca cert (friendlyname)" +./hxtool query \ + --pass=PASS:foobar \ + --friendlyname=ca \ + PKCS12:$srcdir/data/test.p12 || exit 1 + +echo "make sure entry is not found (friendlyname)" +./hxtool query \ + --pass=PASS:foobar \ + --friendlyname=friendlyname-test \ + PKCS12:$srcdir/data/sub-cert.p12 && exit 1 + +echo "make sure entry is found (friendlyname|private key)" +./hxtool query \ + --pass=PASS:foobar \ + --friendlyname=friendlyname-test \ + --private-key \ + PKCS12:$srcdir/data/test.p12 || exit 1 + +echo "make sure entry is not found (friendlyname|private key)" +./hxtool query \ + --pass=PASS:foobar \ + --friendlyname=ca \ + --private-key \ + PKCS12:$srcdir/data/test.p12 && exit 1 + +exit 0 + diff --git a/third_party/heimdal/lib/hx509/data/sub-ca.crt b/third_party/heimdal/lib/hx509/data/sub-ca.crt new file mode 100644 index 0000000..25f3ae8 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/sub-ca.crt @@ -0,0 +1,123 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 10 (0xa) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Mar 22 22:25:10 2019 GMT + Not After : Nov 21 22:25:10 2518 GMT + Subject: C=SE, CN=Sub CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:c7:18:39:67:2a:c4:6b:c6:1a:64:23:bb:ba:4c: + 47:22:35:91:b7:c9:eb:57:b9:8b:8f:83:62:be:0a: + 56:49:cc:ed:de:7e:f9:44:db:8f:f9:f9:ec:db:a2: + 4a:d3:fa:b1:36:c0:93:e9:2b:d0:9a:64:65:43:52: + 64:0e:af:3c:0a:23:57:d9:66:44:0c:ef:a6:73:7e: + 4d:71:94:76:5d:d2:2e:9c:02:1e:44:4b:67:0d:61: + 05:ff:f1:cc:29:94:93:ab:f7:b6:d7:33:d0:9e:b4: + 02:1a:7b:03:bb:9c:52:00:21:43:97:ff:59:f3:b1: + eb:16:67:b1:5a:66:26:99:04:12:28:bb:68:97:38: + 66:cf:d3:cc:da:41:d8:4f:e2:f9:59:48:da:ca:55: + b9:2a:63:43:6b:0d:c5:58:75:8e:6e:55:d2:77:cd: + df:8a:14:82:a2:72:f3:e8:93:a1:e4:72:f3:c0:93: + b3:0b:72:98:ad:53:93:53:86:fc:b0:3b:77:1c:aa: + f5:64:77:ce:92:0c:07:82:60:39:e9:d6:bc:df:dc: + ad:f9:4f:42:d2:db:42:76:6e:0b:f5:fa:58:05:7f: + 3c:d9:cf:eb:d2:c0:9a:26:2c:e8:90:73:0a:3c:42: + e5:f9:0b:cd:53:2d:16:14:75:f8:47:2e:04:1a:47: + d8:a6:20:0f:ec:96:fe:14:30:87:30:84:04:74:42: + 45:b3:3b:c1:48:84:54:4e:69:9b:f5:cb:7a:da:75: + 1e:26:93:87:5e:a2:c6:8f:fd:0f:96:84:76:2d:18: + 86:f7:87:1e:95:47:10:45:b5:45:ea:38:b7:e0:22: + 28:c6:98:42:5f:ed:69:d6:73:a3:d4:72:de:74:f7: + 2a:d2:90:5d:66:86:a1:b5:a4:fb:c7:37:94:65:82: + 80:d7:88:84:be:d6:5f:fd:25:88:0b:ee:6b:bb:4b: + 94:c6:e1:39:95:74:93:44:44:8e:3f:7e:13:33:49: + 8e:e3:f4:a0:43:e7:2d:15:f7:02:e9:bf:a8:94:65: + 71:df:45:35:f7:cc:03:b6:e4:d6:32:d2:98:66:ba: + d6:da:76:35:e0:81:76:25:0a:94:3f:6c:a6:53:49: + 52:c5:38:44:4d:ea:b4:fd:50:ee:63:e1:1b:51:ef: + 62:64:0e:39:cb:10:73:9d:fd:b0:2e:15:5a:cb:90: + 1c:9f:e9:88:37:14:92:32:7b:7a:00:fd:35:b4:d3: + 8c:99:90:74:95:7d:bf:25:41:04:68:56:38:3e:f1: + f5:97:b5:f3:cc:b8:16:99:40:1f:9d:eb:51:88:46: + 2a:62:b9:a5:bd:ad:97:db:58:5a:d4:6c:ed:32:db: + b4:5a:f5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 63:34:08:C8:42:04:47:74:99:65:DD:4F:EA:C5:0F:05:D9:F8:CE:47 + X509v3 Authority Key Identifier: + keyid:53:B8:CC:09:C6:9F:42:EA:D5:E4:74:20:B4:65:ED:68:F8:9D:B5:05 + DirName:/CN=hx509 Test Root CA/C=SE + serial:8D:F8:0A:D8:C1:70:91:C4 + + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment, Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 77:0b:fc:11:37:04:49:92:2b:97:e1:ee:b6:94:33:11:be:bb: + db:8b:6e:ce:42:11:39:b2:be:61:03:a2:ef:d4:06:1f:63:d2: + af:1f:c5:43:80:67:1d:10:a0:3d:93:d1:7f:bd:be:9e:21:48: + d0:a8:ea:8c:32:0a:f7:eb:b0:c7:0f:ac:a7:8b:c6:1a:18:10: + 51:88:fd:1a:53:4b:1b:7b:94:5e:59:02:92:72:6c:df:32:3a: + 9c:f5:87:c9:fd:a2:f8:d3:df:34:be:75:7e:51:15:eb:b0:df: + 87:1b:15:df:fc:97:1e:06:f9:6e:8b:79:45:3d:c4:76:d2:1d: + 8e:04:8f:72:d6:b0:7c:09:79:23:47:7a:9a:41:76:7e:c3:3d: + 2d:46:26:db:72:64:a8:1d:ca:94:fe:d8:69:e7:24:1f:dc:c8: + 7b:4f:2f:89:7b:a3:8c:33:7f:0f:54:16:f4:45:60:e1:df:68: + f5:5b:3a:ce:1c:63:e6:81:ca:a6:aa:e4:a2:c1:07:e3:ec:ef: + ef:ad:cc:ac:5a:e1:57:40:15:09:b3:0f:f1:58:b2:2a:45:eb: + 5e:16:03:9c:2c:c1:ce:22:48:67:06:5e:0a:fd:fd:d5:76:8e: + a8:db:2c:38:15:b4:c1:e4:0f:12:98:0a:43:19:e6:74:b9:8b: + e3:7a:92:2e:2a:30:1d:b7:85:39:d5:29:2f:54:16:7d:b0:f6: + f9:17:e2:95:07:ff:0f:e6:16:55:6d:97:c8:41:c6:5f:8f:a9: + 3c:3a:19:8d:66:29:13:f3:00:6d:31:f3:f1:14:a5:e8:c7:2c: + c0:18:4b:5e:15:88:eb:59:44:97:91:1c:78:d7:a0:4d:a1:bf: + bf:b0:67:4f:68:df:d3:d0:c4:6e:b8:1d:36:bd:a8:c8:b4:67: + 34:c0:b2:28:8a:e9:1a:30:14:b3:be:d5:a3:a0:57:4f:b7:ff: + a0:9e:c0:28:58:90:43:57:e7:7c:d0:81:90:41:54:85:56:4b: + cd:f4:a3:63:3b:1a:8f:82:0d:2c:9d:79:58:40:f4:f6:37:a0: + fc:77:db:82:ab:de:fa:0c:7f:c2:ce:35:80:4e:f7:d8:0d:8b: + cd:5b:8c:a9:82:ec:a3:a1:ca:b8:4e:29:fd:35:79:dc:4d:f3: + bf:ee:41:a0:88:63:b9:65:22:bb:0d:27:e8:91:d4:20:51:06: + f9:e7:9a:e9:7c:4c:4a:64:b5:4f:22:79:36:ad:79:e8:b8:6a: + 6f:f8:e8:39:48:7b:3f:87:14:9a:22:ec:7d:33:94:35:42:29: + 56:11:de:15:bd:4c:c2:5d:ff:9f:82:72:a2:00:b3:e9:68:38: + 5b:ab:dd:0d:90:73:cd:80 +-----BEGIN CERTIFICATE----- +MIIFXzCCA0egAwIBAgIBCjANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMCAXDTE5MDMyMjIyMjUxMFoYDzI1 +MTgxMTIxMjIyNTEwWjAeMQswCQYDVQQGEwJTRTEPMA0GA1UEAwwGU3ViIENBMIIC +IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxxg5ZyrEa8YaZCO7ukxHIjWR +t8nrV7mLj4NivgpWSczt3n75RNuP+fns26JK0/qxNsCT6SvQmmRlQ1JkDq88CiNX +2WZEDO+mc35NcZR2XdIunAIeREtnDWEF//HMKZSTq/e21zPQnrQCGnsDu5xSACFD +l/9Z87HrFmexWmYmmQQSKLtolzhmz9PM2kHYT+L5WUjaylW5KmNDaw3FWHWOblXS +d83fihSConLz6JOh5HLzwJOzC3KYrVOTU4b8sDt3HKr1ZHfOkgwHgmA56da839yt ++U9C0ttCdm4L9fpYBX882c/r0sCaJizokHMKPELl+QvNUy0WFHX4Ry4EGkfYpiAP +7Jb+FDCHMIQEdEJFszvBSIRUTmmb9ct62nUeJpOHXqLGj/0PloR2LRiG94celUcQ +RbVF6ji34CIoxphCX+1p1nOj1HLedPcq0pBdZoahtaT7xzeUZYKA14iEvtZf/SWI +C+5ru0uUxuE5lXSTRESOP34TM0mO4/SgQ+ctFfcC6b+olGVx30U198wDtuTWMtKY +ZrrW2nY14IF2JQqUP2ymU0lSxThETeq0/VDuY+EbUe9iZA45yxBznf2wLhVay5Ac +n+mINxSSMnt6AP01tNOMmZB0lX2/JUEEaFY4PvH1l7XzzLgWmUAfnetRiEYqYrml +va2X21ha1GztMtu0WvUCAwEAAaOBmTCBljAdBgNVHQ4EFgQUYzQIyEIER3SZZd1P +6sUPBdn4zkcwWgYDVR0jBFMwUYAUU7jMCcafQurV5HQgtGXtaPidtQWhLqQsMCox +GzAZBgNVBAMMEmh4NTA5IFRlc3QgUm9vdCBDQTELMAkGA1UEBhMCU0WCCQCN+ArY +wXCRxDAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIB5jANBgkqhkiG9w0BAQUFAAOC +AgEAdwv8ETcESZIrl+HutpQzEb6724tuzkIRObK+YQOi79QGH2PSrx/FQ4BnHRCg +PZPRf72+niFI0KjqjDIK9+uwxw+sp4vGGhgQUYj9GlNLG3uUXlkCknJs3zI6nPWH +yf2i+NPfNL51flEV67DfhxsV3/yXHgb5bot5RT3EdtIdjgSPctawfAl5I0d6mkF2 +fsM9LUYm23JkqB3KlP7YaeckH9zIe08viXujjDN/D1QW9EVg4d9o9Vs6zhxj5oHK +pqrkosEH4+zv763MrFrhV0AVCbMP8ViyKkXrXhYDnCzBziJIZwZeCv391XaOqNss +OBW0weQPEpgKQxnmdLmL43qSLiowHbeFOdUpL1QWfbD2+RfilQf/D+YWVW2XyEHG +X4+pPDoZjWYpE/MAbTHz8RSl6McswBhLXhWI61lEl5EceNegTaG/v7BnT2jf09DE +brgdNr2oyLRnNMCyKIrpGjAUs77Vo6BXT7f/oJ7AKFiQQ1fnfNCBkEFUhVZLzfSj +Yzsaj4INLJ15WED09jeg/Hfbgqve+gx/ws41gE732A2LzVuMqYLso6HKuE4p/TV5 +3E3zv+5BoIhjuWUiuw0n6JHUIFEG+eea6XxMSmS1TyJ5Nq156Lhqb/joOUh7P4cU +miLsfTOUNUIpVhHeFb1Mwl3/n4JyogCz6Wg4W6vdDZBzzYA= +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/sub-ca.key b/third_party/heimdal/lib/hx509/data/sub-ca.key new file mode 100644 index 0000000..1475e42 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/sub-ca.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDHGDlnKsRrxhpk +I7u6TEciNZG3yetXuYuPg2K+ClZJzO3efvlE24/5+ezbokrT+rE2wJPpK9CaZGVD +UmQOrzwKI1fZZkQM76Zzfk1xlHZd0i6cAh5ES2cNYQX/8cwplJOr97bXM9CetAIa +ewO7nFIAIUOX/1nzsesWZ7FaZiaZBBIou2iXOGbP08zaQdhP4vlZSNrKVbkqY0Nr +DcVYdY5uVdJ3zd+KFIKicvPok6HkcvPAk7MLcpitU5NThvywO3ccqvVkd86SDAeC +YDnp1rzf3K35T0LS20J2bgv1+lgFfzzZz+vSwJomLOiQcwo8QuX5C81TLRYUdfhH +LgQaR9imIA/slv4UMIcwhAR0QkWzO8FIhFROaZv1y3radR4mk4deosaP/Q+WhHYt +GIb3hx6VRxBFtUXqOLfgIijGmEJf7WnWc6PUct509yrSkF1mhqG1pPvHN5RlgoDX +iIS+1l/9JYgL7mu7S5TG4TmVdJNERI4/fhMzSY7j9KBD5y0V9wLpv6iUZXHfRTX3 +zAO25NYy0phmutbadjXggXYlCpQ/bKZTSVLFOERN6rT9UO5j4RtR72JkDjnLEHOd +/bAuFVrLkByf6Yg3FJIye3oA/TW004yZkHSVfb8lQQRoVjg+8fWXtfPMuBaZQB+d +61GIRipiuaW9rZfbWFrUbO0y27Ra9QIDAQABAoICAHBMg6RjhSNdPGmbljoA6Gat +XKIULMDwkX3DmCClaAJ8qvdDG4rxZYaUqDtCkX57+xVtDoEJC8LqOgv9Hx8BTJZT +VSv0+RFq47JlXX1hRlqpQU0SDMxs05XCUkYJtyUE/z6SnPlJ6rR5yG3zUSmzhLU6 +DgxgJfbFNlsO5gSddcv9ddivzNDvKV60kunRFhgJaKgp5e8W5zi3gMGTpOq+dDZc +Bjk5UItsAjtrJ5TaIQjgpgjLxsQAQYoSiBknHMSy5f6vl3ax9Tx/uISbjk8Npr+G +lEL5qDGTJyvx6qE2Mgv3tvUMyHG53bkGv68qlG1lNp6BP7FYzwl/eSl9FSdVuycK +UsUMi+dpuQlXOVprKAKTxYw+E7n8TV7ewmudbOEFR/ao6qCJqNtSQJa5dFFhU9An +ld/rKIcY9gfobYtS0qRiGAt18Be7qt6qGpwAZogfe+VM/G3S00yVP21gGN2qju3M +6vF99CTVLeD+g8JUJT+olzShLpZAgw09hXMx1JJJksl+kv6FNG0EotxlXCdIQTsG +TtWvOFXck7E5FZHjj+5eXCyRNVKzWRJAU6POr3Qr0gLpcg0DBbzfLAvDEA8k3V2Y +DqQeyi7xrd7ALKZmrLWnLQQdXQ8rUN0f/8lsus3TOiXjly3/GIediaYb+uxdACmC +4d+twAWpdnWrAiWDaICBAoIBAQDm7vUgSu2rsbd+YvBhYrNhTmmyVr/5HWOGaDjX +YJWj2Vqh4sVeoVjRpVgC4Yyx/iE9f4MPsiBzWmudMuG/yytxIfWWXEBGXmAHYL8Z +d6acVWer0yZik/xYV8nUUVUzzB7EvB7XdFtGMYPTZNiqhyZ9CGMeIHcaXndqejeJ +ycbOr+IDgBKQ9fGdpAZjTprrB0WqOhnxy6EJoObg6bicgIPCBxzdVCDo6mmkkRrQ +lIYRMAtjIzbGdwT6OADUf9Lr2aPBuKBQeEKFbADyNNyenqvcSFKcGcug2DZ8sIYN +US28VHke87mOg6qrNh166e00Hlp0q42Q2hV/8XxRQDDwxoqFAoIBAQDctIx8lGcJ +kxftf5j7ss0iUYSkT77HF7V9q81X7iMSjHTEyIYD2UHt2PS0gUL1jnjOXjIDFFHU +HzfymvsEjV8Vr8nUvKVkSUXWFnYPQ4rFP2d+Zyv64AhDKRrIOiG9ozLhqDdu7wui +XXigEuuwG6+LObO09FwKOhDRNgpuQnDlgHPidyu4PHoz56SlzGpTXM1/nTIGkWMi +v2aZF2hAzQM3bEqeyRUTnX/DvOQbFLDYLDc/KWaPDvBTJCwa2tPSZRA5ArmEmloc +yxTdf+DaSBy7P2EExfXkKNgvO978GYHUBk3SdA/2BLy0kNU1BSrajtjrxSLqUD8j +aVYafGb5eNGxAoIBAQCBZOkCVBmBt406CtPnrTcXUalVnNfqDHaEjAc1Xs/Zw+LN +jFPMpxkuNrfuvVRpMxyK6dSUydj26XYc2bK2FW/c7ws9WalGBIFIAQRyj6FSPWRe +WWxLleGx2lajWYMlB71BvKqHTJIL7ZiQrRPd0OZW7okjC0vRAZdlmN9fnCiCDPjV +v0An6zabfpl5sUSKZkO5kt6QpekwjPBwm2SuhC/PWs7okMfz2cyhwhBFSMMqBEKN +JOD/KRcn4JNOfeS/8+2WkQ16qTeUrKSHEemAEyX2wqtO/gEjuaImEX67HX5D5Q0M +s8GHweyyDBtOkJ4xMsS6VJl4zUl4q+VdXVtOveBFAoIBAEbpl+37PLP92AVOJxhQ +Fcr+CDFHEhQkEQNE7SBgelJeYLJNf4nDB4TlXZKVqa7+TOB5sXX91GDkevRvSVHo +HnH4XlAFINr9E/w6kUpMOE0yFw2tFptv2hfCIEHPM8IbqqCIjO8OzV0ozTYZfjLC +Yn/IVW5ByUTb7UVbKLTOkjmbMSDFi32RqO3+co93A36vZbOoDUfA9OpYNx3fQHb5 +qBvppnwoPaZkx4Vbrqro1f1PD50yryot8Ze1GpqyTrbeE/1NW9A4S9XOhnC4wsU/ +wEOFlKWU+XGKkhNzGC1GAMngEKca9XnlgcA+fNKhS2iX1yjB2XsRt4eoM6sk520m +nbECggEBAM2u917mgRcyRrOF3orTy0p5aRkHmAi7rdlr/E2CC/I+Uk00cSEJKgfL +IzLOs5ZARc6kkBAilNhz8lWWADaonmE5qDZjAzYwIuNWlZgWGYO74RwpavNaK7UM +MhRWCzomZUyNHKJiubkM8CTaioVsqoZS/OiWGHtGtSTAAknCb1wc5fppNU0xUQ/5 +AZGlrpUdb86VGN/lNNsF16tZ0mWUazXMXDCZgT9869p41OQYgIGDPvf9y9mWyYR6 +VbQSyfvDh4Wiu4Sf7L6OP8VG+xvhD+sRZPB9i3TzvhFWrzkcP3sXRqPxpdSSWgyP +Ca7fU8eAAjotw7SSdeefJ+CduL/cNQE= +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/sub-cert.crt b/third_party/heimdal/lib/hx509/data/sub-cert.crt new file mode 100644 index 0000000..b98c463 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/sub-cert.crt @@ -0,0 +1,116 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 11 (0xb) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=SE, CN=Sub CA + Validity + Not Before: Mar 22 22:25:12 2019 GMT + Not After : Nov 21 22:25:12 2518 GMT + Subject: C=SE, CN=Test sub cert + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:ef:45:00:67:2b:7e:d2:ea:7d:80:b1:ae:81:5e: + fb:dd:82:ca:de:db:98:37:70:e8:3c:a2:01:87:8b: + 88:2e:40:30:22:d4:65:1d:7e:cb:cb:d5:40:e0:51: + 06:f0:f3:d9:00:db:5d:6a:0f:d3:11:bc:a1:3c:69: + 25:65:a9:87:b5:8a:3e:6c:79:2a:e8:5b:1a:9e:b4: + a4:81:5b:c3:83:f6:fd:9a:a8:48:6a:c4:ce:7f:81: + 26:83:c9:e5:b5:c9:a2:18:ed:0c:ea:1a:26:59:49: + df:56:ea:c2:33:2f:65:c2:14:30:5d:78:4e:91:09: + 6d:f5:77:ee:e8:0e:fe:ca:14:92:af:73:c4:8e:91: + b1:62:1a:c1:46:3e:36:d2:33:6a:7f:05:4e:d5:7b: + fe:69:4f:6c:b1:be:89:e6:7e:8d:5b:de:10:6c:a6: + bc:4a:05:66:17:19:71:e3:2c:62:bf:8b:4b:3c:6d: + fb:2a:7b:95:d5:d4:02:f0:43:e0:ce:cc:7a:30:fb: + a9:93:d2:50:a0:17:67:c6:08:8d:3c:9c:83:69:1f: + b7:ab:cf:d0:77:b6:8e:cc:89:0d:82:cd:e1:fb:53: + 2c:1d:f6:6b:81:0d:8f:da:dc:6a:34:93:06:23:32: + fb:83:90:40:8a:7f:ad:cf:2c:81:6a:10:cb:59:29: + d4:f2:af:b2:ee:f0:7b:b2:d5:0f:9d:5c:e6:d3:eb: + 18:9b:89:01:11:5f:e7:f4:50:34:e6:2c:31:b1:f3: + 60:af:03:a5:40:00:47:88:76:cd:52:da:1b:11:03: + 57:f5:3d:a1:01:f6:2f:9e:f5:01:37:22:a0:7d:5f: + 40:87:2d:69:72:70:80:05:16:24:2d:a6:b1:5e:ca: + 40:ad:f2:da:7f:c9:8f:7a:32:b2:8c:be:9b:de:66: + 17:92:81:83:8d:1a:f5:c9:8b:9a:3b:4a:84:b2:24: + 63:97:60:f6:3a:c0:84:88:2a:dd:6b:f8:e7:44:29: + 79:cf:98:d9:ab:36:93:10:a8:7a:7b:90:bc:bb:e0: + 43:c1:93:13:80:9d:cb:a6:68:67:94:67:6b:3a:58: + bd:02:39:20:88:e1:64:8e:a1:7a:6b:99:3b:9b:00: + 65:11:b5:fd:b7:18:55:fe:67:f4:94:ab:c2:08:a7: + 3a:d8:a7:b4:6e:d9:e9:89:1e:b0:81:1e:23:31:a9: + 17:b7:c7:f9:df:5b:90:2c:46:96:c5:d5:a6:cc:8b: + e4:db:fd:4b:47:8d:8f:bb:e4:41:d0:99:fe:81:83: + 88:a7:f0:a5:81:ae:c9:62:f6:4f:d8:12:60:33:20: + 6f:d1:39:37:f5:1f:05:40:62:43:9b:97:a5:7b:16: + cc:93:e5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 48:26:75:6B:4D:E0:98:93:39:02:40:D3:F1:1C:6D:D0:D8:45:A6:04 + Signature Algorithm: sha1WithRSAEncryption + aa:a0:db:44:96:6c:b5:c7:96:93:a3:11:e5:dc:1f:69:08:87: + f5:5f:50:25:99:03:6c:d2:89:55:4c:04:d4:8a:49:73:e8:e1: + 82:4f:f6:45:24:1c:ef:46:09:b2:19:09:16:5f:11:05:13:e7: + 3f:ca:5b:af:4f:6f:39:df:a8:71:1c:cb:62:2b:8d:42:b9:a7: + 58:76:72:db:88:8d:3a:e0:33:5c:ef:41:c7:30:d6:d0:9a:9c: + 70:f1:72:74:e6:0d:6c:1c:11:ff:f3:4a:ee:3d:d2:f7:3a:56: + 9f:41:63:83:60:4c:6b:63:d5:9a:a1:c8:22:b2:a5:8c:03:99: + 2f:04:65:a8:52:1b:1c:cb:4b:e4:b1:a0:86:7c:d7:85:e9:9a: + 8b:8f:f1:2d:e9:45:d0:f4:ee:51:cf:13:da:ff:ea:e8:cc:30: + cc:ed:f3:7e:f9:4d:59:a3:d2:ca:f2:4f:5b:73:65:63:de:39: + 0e:87:e1:16:30:65:d0:fa:da:0d:57:df:82:de:09:2c:24:7a: + ef:9c:d8:fa:7c:5a:25:f1:1e:e3:e1:56:c5:79:c3:13:37:38: + 03:dd:b4:6f:c0:61:b7:cb:41:bb:77:0c:c3:4f:14:e0:8c:e9: + 89:4b:55:6b:dc:ce:11:9b:f0:68:32:e2:64:c8:75:6a:80:26: + 88:fc:c1:ad:56:07:57:07:2d:fc:10:c8:42:94:f6:f4:7a:e2: + 94:ee:05:aa:28:7a:f3:d6:62:4a:fb:99:c0:df:dd:ca:77:14: + 70:6e:63:d1:68:25:6b:de:51:8b:8c:0c:5e:68:79:25:a5:68: + 74:c1:43:23:75:4f:eb:30:c6:84:79:a9:df:25:a6:66:56:cd: + 9c:95:40:b0:12:c0:60:9d:b3:99:02:4d:d1:de:25:2d:00:49: + e4:8f:81:8f:14:5d:3e:1c:c4:ac:11:ac:ef:0d:a7:ca:0c:01: + 88:54:26:bb:38:c7:24:b8:4b:45:97:40:9b:21:ea:7b:e0:5b: + 5f:d4:3d:dc:01:0a:8e:3d:db:31:8b:e8:23:8b:5c:48:34:95: + de:71:cc:61:43:aa:59:0e:be:0a:7f:75:8d:fb:b9:f0:fd:28: + e9:76:8d:5f:ea:9c:59:07:28:a5:b4:df:8f:0b:3c:c7:ad:00: + fe:9e:28:86:cd:52:fe:e3:78:81:ed:5e:73:40:1c:06:02:a8: + b1:84:b3:ec:56:ce:a3:70:22:ce:ab:0f:4b:8d:36:09:2d:6d: + 5e:93:2d:c4:20:c4:bd:8e:78:68:0a:84:81:b9:85:b7:cb:03: + c0:26:b9:c3:d8:e7:ab:c6:a6:7c:55:a4:e6:96:b3:65:84:5b: + 7e:bd:1e:c9:94:f6:25:c7 +-----BEGIN CERTIFICATE----- +MIIE+TCCAuGgAwIBAgIBCzANBgkqhkiG9w0BAQUFADAeMQswCQYDVQQGEwJTRTEP +MA0GA1UEAwwGU3ViIENBMCAXDTE5MDMyMjIyMjUxMloYDzI1MTgxMTIxMjIyNTEy +WjAlMQswCQYDVQQGEwJTRTEWMBQGA1UEAwwNVGVzdCBzdWIgY2VydDCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAO9FAGcrftLqfYCxroFe+92Cyt7bmDdw +6DyiAYeLiC5AMCLUZR1+y8vVQOBRBvDz2QDbXWoP0xG8oTxpJWWph7WKPmx5Kuhb +Gp60pIFbw4P2/ZqoSGrEzn+BJoPJ5bXJohjtDOoaJllJ31bqwjMvZcIUMF14TpEJ +bfV37ugO/soUkq9zxI6RsWIawUY+NtIzan8FTtV7/mlPbLG+ieZ+jVveEGymvEoF +ZhcZceMsYr+LSzxt+yp7ldXUAvBD4M7MejD7qZPSUKAXZ8YIjTycg2kft6vP0He2 +jsyJDYLN4ftTLB32a4ENj9rcajSTBiMy+4OQQIp/rc8sgWoQy1kp1PKvsu7we7LV +D51c5tPrGJuJARFf5/RQNOYsMbHzYK8DpUAAR4h2zVLaGxEDV/U9oQH2L571ATci +oH1fQIctaXJwgAUWJC2msV7KQK3y2n/Jj3oysoy+m95mF5KBg40a9cmLmjtKhLIk +Y5dg9jrAhIgq3Wv450Qpec+Y2as2kxCoenuQvLvgQ8GTE4Cdy6ZoZ5RnazpYvQI5 +IIjhZI6hemuZO5sAZRG1/bcYVf5n9JSrwginOtintG7Z6YkesIEeIzGpF7fH+d9b +kCxGlsXVpsyL5Nv9S0eNj7vkQdCZ/oGDiKfwpYGuyWL2T9gSYDMgb9E5N/UfBUBi +Q5uXpXsWzJPlAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMB0GA1Ud +DgQWBBRIJnVrTeCYkzkCQNPxHG3Q2EWmBDANBgkqhkiG9w0BAQUFAAOCAgEAqqDb +RJZstceWk6MR5dwfaQiH9V9QJZkDbNKJVUwE1IpJc+jhgk/2RSQc70YJshkJFl8R +BRPnP8pbr09vOd+ocRzLYiuNQrmnWHZy24iNOuAzXO9BxzDW0JqccPFydOYNbBwR +//NK7j3S9zpWn0Fjg2BMa2PVmqHIIrKljAOZLwRlqFIbHMtL5LGghnzXhemai4/x +LelF0PTuUc8T2v/q6MwwzO3zfvlNWaPSyvJPW3NlY945DofhFjBl0PraDVffgt4J +LCR675zY+nxaJfEe4+FWxXnDEzc4A920b8Bht8tBu3cMw08U4IzpiUtVa9zOEZvw +aDLiZMh1aoAmiPzBrVYHVwct/BDIQpT29HrilO4Fqih689ZiSvuZwN/dyncUcG5j +0Wgla95Ri4wMXmh5JaVodMFDI3VP6zDGhHmp3yWmZlbNnJVAsBLAYJ2zmQJN0d4l +LQBJ5I+BjxRdPhzErBGs7w2nygwBiFQmuzjHJLhLRZdAmyHqe+BbX9Q93AEKjj3b +MYvoI4tcSDSV3nHMYUOqWQ6+Cn91jfu58P0o6XaNX+qcWQcopbTfjws8x60A/p4o +hs1S/uN4ge1ec0AcBgKosYSz7FbOo3AizqsPS402CS1tXpMtxCDEvY54aAqEgbmF +t8sDwCa5w9jnq8amfFWk5pazZYRbfr0eyZT2Jcc= +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/sub-cert.key b/third_party/heimdal/lib/hx509/data/sub-cert.key new file mode 100644 index 0000000..481dabb --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/sub-cert.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +G2q8/Es7kVEQkUPyRNnHTWdnKW+vIQ0= +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/sub-cert.p12 b/third_party/heimdal/lib/hx509/data/sub-cert.p12 Binary files differnew file mode 100644 index 0000000..18898c8 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/sub-cert.p12 diff --git a/third_party/heimdal/lib/hx509/data/tcg-devid.pem b/third_party/heimdal/lib/hx509/data/tcg-devid.pem new file mode 100644 index 0000000..66b769c --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/tcg-devid.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAlFeGFt +cGxlQ0EwHhcNMTQwMTE1MTU0MDUwWhcNMTUwMTE1MTU0MDUwWjAAMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAncvm0aOBK05rdNInYXzJGV5SFteVUFpt +XFxg4evROvlulB3BzUmFGQYFDcItVnJX2fAvf0UJLtLBVBQggb5ylL6bRpj72cS3 +oyNbs0CGmix9Z1QDjkZZFvIsD1GcKO0tvsCvsEItH8Cm0fq8WcGFijWLdRD5eulP +55pq1bAHAvIo4+VLMJVBG71xrKGZeHPjKoq6seYjh7AGy+hk2vmFzpZ8Ghdgqv+K +02IZ7FEdzuylHW8U3qsxBHysMut4inj6AiVf467OOs5meHiifIK9MGkovMrfY9iX +uUVUs/KXpE1sgeoX9BLvx1BPcODosr5K+z5i71OtIXy4CXrPvcGzRwIDAQABo4IB +hzCCAYMwQAYIKwYBBQUHAQEENDAyMDAGCCsGAQUFBzAChiRodHRwOi8vd3d3LmV4 +YW1wbGUuY29tL0V4YW1wbGVDQS5jcnQwDgYDVR0PAQH/BAQDAgAgMIGBBgNVHREB +Af8EdzB1pEswSTEWMBQGBWeBBQIBDAtpZDo1NDQzNDcwMDEXMBUGBWeBBQICDAxB +QkNERUYxMjM0NTYxFjAUBgVngQUCAwwLaWQ6MDAwMTAwMjOgJgYIKwYBBQUHCASg +GjAYBgVngQUBAgQPdHBtc2VyaWFsbnVtYmVyMAwGA1UdEwEB/wQCMAAwNQYDVR0f +BC4wLDAqoCigJoYkaHR0cDovL3d3dy5leGFtcGxlLmNvbS9FeGFtcGxlQ0EuY3Js +MBAGA1UdIAQJMAcwBQYDKgMEMB8GA1UdIwQYMBaAFDR3ZyRMRK/nnirgskxpV5Uk +sz3aMBAGA1UdJQQJMAcGBWeBBQgBMCEGA1UdCQQaMBgwFgYFZ4EFAhAxDTALDAMy +LjACAQACAWMwDQYJKoZIhvcNAQELBQADggEBABtrZu0n/7jPTYxak2n30AUakS7f +Ihomojo14e8Lp/HF7/2VaUcohJH4KekCHTf8wpPxM/b9xRKLSOORA2Ey255Q2h8T +v19he0dcdTvDPNQVY3AKaFO4cNiXeOYPR8n3IDYK5QdPqrdRX4/Bc34QcTWFDALx +C00L/kDvBjV7l0Et2DBJIiBNziVKxs1xn136buZYRam6ZJhTRzNMMQ0eZ279Um4M +39EI4DIFv6FzX0sC5waacVg6HFYd933NtdkDWV0VTGuk+5V8rH4Sjx+sywHahkoz +BJhQBai2qiWEt7bB0ExGN2ZXPjiQiG4UHvLgGlCOUHX7EDNf0dvfUIZ6hLY= +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/tcg-ek-cp.pem b/third_party/heimdal/lib/hx509/data/tcg-ek-cp.pem new file mode 100644 index 0000000..f6631b2 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/tcg-ek-cp.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBATANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAlFeGFt +cGxlQ0EwHhcNMTQwMTE1MTU0MDUwWhcNMTUwMTE1MTU0MDUwWjAAMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAncvm0aOBK05rdNInYXzJGV5SFteVUFpt +XFxg4evROvlulB3BzUmFGQYFDcItVnJX2fAvf0UJLtLBVBQggb5ylL6bRpj72cS3 +oyNbs0CGmix9Z1QDjkZZFvIsD1GcKO0tvsCvsEItH8Cm0fq8WcGFijWLdRD5eulP +55pq1bAHAvIo4+VLMJVBG71xrKGZeHPjKoq6seYjh7AGy+hk2vmFzpZ8Ghdgqv+K +02IZ7FEdzuylHW8U3qsxBHysMut4inj6AiVf467OOs5meHiifIK9MGkovMrfY9iX +uUVUs/KXpE1sgeoX9BLvx1BPcODosr5K+z5i71OtIXy4CXrPvcGzRwIDAQABo4IB +XjCCAVowQAYIKwYBBQUHAQEENDAyMDAGCCsGAQUFBzAChiRodHRwOi8vd3d3LmV4 +YW1wbGUuY29tL0V4YW1wbGVDQS5jcnQwDgYDVR0PAQH/BAQDAgAgMFkGA1UdEQEB +/wRPME2kSzBJMRYwFAYFZ4EFAgEMC2lkOjU0NDM0NzAwMRcwFQYFZ4EFAgIMDEFC +Q0RFRjEyMzQ1NjEWMBQGBWeBBQIDDAtpZDowMDAxMDAyMzAMBgNVHRMBAf8EAjAA +MDUGA1UdHwQuMCwwKqAooCaGJGh0dHA6Ly93d3cuZXhhbXBsZS5jb20vRXhhbXBs +ZUNBLmNybDAQBgNVHSAECTAHMAUGAyoDBDAfBgNVHSMEGDAWgBQ0d2ckTESv554q +4LJMaVeVJLM92jAQBgNVHSUECTAHBgVngQUIATAhBgNVHQkEGjAYMBYGBWeBBQIQ +MQ0wCwwDMi4wAgEAAgFjMA0GCSqGSIb3DQEBCwUAA4IBAQAba2btJ/+4z02MWpNp +99AFGpEu3yIaJqI6NeHvC6fxxe/9lWlHKISR+CnpAh03/MKT8TP2/cUSi0jjkQNh +MtueUNofE79fYXtHXHU7wzzUFWNwCmhTuHDYl3jmD0fJ9yA2CuUHT6q3UV+PwXN+ +EHE1hQwC8QtNC/5A7wY1e5dBLdgwSSIgTc4lSsbNcZ9d+m7mWEWpumSYU0czTDEN +Hmdu/VJuDN/RCOAyBb+hc19LAucGmnFYOhxWHfd9zbXZA1ldFUxrpPuVfKx+Eo8f +rMsB2oZKMwSYUAWotqolhLe2wdBMRjdmVz44kIhuFB7y4BpQjlB1+xAzX9Hb31CG +eoS2 +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/test-ds-only.crt b/third_party/heimdal/lib/hx509/data/test-ds-only.crt new file mode 100644 index 0000000..ce0de74 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test-ds-only.crt @@ -0,0 +1,117 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 5 (0x5) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Mar 22 22:25:05 2019 GMT + Not After : Nov 21 22:25:05 2518 GMT + Subject: C=SE, CN=Test cert DigitalSignature + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:d2:e5:b6:27:f7:6c:c1:d0:ba:8a:4a:6a:4e:b5: + a6:92:2e:5b:98:d7:0c:6a:7e:f4:bf:19:30:2d:ee: + 1c:5a:ee:28:f6:5c:a8:12:03:20:c7:e8:2b:b1:44: + 9f:b7:54:27:6e:17:fc:c0:f6:f7:ea:38:d2:c8:77: + ab:6a:ae:d1:ab:9f:1e:79:df:8a:51:55:aa:6c:6a: + 13:74:74:2f:c0:20:57:ef:f3:e1:71:da:b0:ec:62: + e9:8a:01:da:f6:e6:c6:5a:fe:11:61:58:5c:a0:01: + ec:0e:af:70:0d:72:94:a1:d4:1c:76:53:ae:39:a0: + cf:70:d8:d9:7c:95:18:2b:5f:36:00:2f:5c:be:a2: + d5:8e:0e:e3:aa:76:0c:1f:86:b3:69:fe:e4:29:0a: + 30:b1:ca:83:1a:f2:88:fc:91:2f:58:be:a4:a0:25: + 82:bf:16:b3:ca:70:09:7e:cf:29:f9:2e:58:0b:4a: + 3a:3c:6d:e7:05:63:d5:53:90:ed:ee:96:9e:8e:d7: + a8:ef:50:8b:37:bd:dc:88:f5:12:bc:04:4e:e4:f3: + ec:5d:9d:e6:46:14:e1:e1:6b:15:ab:f4:52:f6:12: + 76:ae:2d:a7:65:ec:8f:bd:90:51:52:4d:e7:cf:ba: + 23:01:7a:85:8b:22:41:a6:98:08:e4:33:00:c1:e2: + 82:b0:b2:c6:f4:6a:34:c6:a9:d7:b1:cc:c6:1a:0b: + ad:69:1f:89:af:e0:63:cd:51:c9:36:7f:08:f0:31: + 97:ea:78:bb:ae:21:4c:aa:2d:32:de:36:03:cf:64: + f8:8a:c0:c5:b3:c4:f9:79:74:7a:8b:d5:ec:bf:19: + 87:c9:25:0c:99:7d:56:a3:93:68:97:c3:cc:08:fb: + 37:c0:2c:cb:87:f2:b4:4e:fe:ce:86:69:2b:8e:c3: + 9e:40:a9:b6:43:6e:d6:b6:3d:08:43:24:09:58:8d: + af:d2:5d:1c:0e:cd:bc:e3:0b:b3:4b:a5:69:a8:3c: + d7:07:d0:7f:d7:78:c7:5c:a4:9f:e1:a2:bc:76:77: + 80:25:0e:82:2b:43:1e:e4:67:49:47:d9:65:45:57: + ed:59:d7:6e:a1:8d:76:a0:c2:65:52:c8:c8:57:5d: + dd:b4:d2:4f:27:a5:08:f1:88:7e:d2:3e:5d:60:c6: + 67:fb:c9:19:e7:78:cc:41:6d:24:11:cd:a4:e6:cf: + 56:8c:41:4d:af:d6:e2:22:c0:a3:64:2c:4b:27:f6: + b3:87:9d:08:e6:2a:2f:db:c8:50:57:95:a3:cf:67: + 77:f8:80:15:f3:45:00:47:f8:80:6e:21:b5:80:f1: + 81:29:45:3f:a9:8a:e2:12:12:4d:c4:90:e3:da:ab: + 08:80:bd + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation + X509v3 Subject Key Identifier: + C4:44:DE:34:6C:55:F0:21:00:F4:CF:F0:55:67:92:FB:8F:B3:40:46 + Signature Algorithm: sha1WithRSAEncryption + a3:9c:c7:b7:3d:fc:8e:3d:5b:58:98:b0:05:63:fd:a7:50:c2: + d4:e8:c2:48:b8:b0:a8:e3:f9:c2:8b:11:47:a1:11:5e:e8:4d: + 75:c5:b8:d9:ec:af:81:95:1e:ec:d8:f6:8a:b6:17:12:ab:d4: + 30:84:cb:35:6a:c8:50:5e:1c:55:26:77:ee:84:f0:80:92:95: + c3:37:50:b3:23:21:7a:3b:63:5a:18:e4:48:fc:de:9b:26:50: + 38:9e:2f:a3:ad:03:5f:0c:b0:a1:0e:41:0b:01:71:b9:a2:df: + 84:f6:c4:d6:9d:8b:f7:a8:ed:cc:7e:b6:8c:5c:bc:26:0c:97: + 77:15:dc:fb:66:4b:0d:01:d9:8e:58:8e:1c:bf:35:47:b8:10: + d4:12:e5:80:09:b3:d8:4a:f4:0a:3f:6a:2f:9f:47:16:80:a7: + 92:6a:d4:3b:79:7b:25:b9:3e:14:a9:90:4e:92:6e:92:7b:6f: + 04:3a:0d:c6:63:77:82:e2:2d:e9:24:63:ce:a0:b1:8c:23:1d: + db:79:b8:4f:77:b8:7f:d2:49:5d:b4:60:a0:78:bb:d6:d7:56: + ff:23:c1:fa:46:cd:9a:2b:0d:87:df:b5:98:eb:7e:fd:af:6e: + 9d:03:de:d3:97:e7:19:09:20:13:ce:2e:b5:89:f0:47:ad:b2: + 3d:f1:5e:77:8b:dd:d3:6e:e2:a8:3c:cd:6a:22:a1:63:92:8c: + 2e:ca:0a:0d:aa:2c:15:98:de:27:08:e5:ee:a5:e0:e5:54:30: + 26:2f:32:ab:c3:de:e0:82:32:2a:dd:39:cb:3c:75:95:8f:9e: + 37:34:34:80:14:27:aa:c6:89:d3:8f:7a:35:19:3b:8b:c1:56: + 06:76:b3:0c:12:05:10:f4:5a:62:ff:d5:ef:e0:f8:da:aa:dc: + 2b:14:73:ad:31:c8:da:19:fe:54:51:32:0f:3b:7f:13:21:0d: + 5c:4f:33:e7:07:92:36:fd:01:04:d4:e6:4c:ba:dc:b4:75:c0: + f6:1f:3c:5a:4a:34:40:87:3b:8c:44:60:de:11:8d:18:41:0a: + e4:e9:d6:19:f5:7b:8f:53:3c:d8:3d:7c:4f:f4:b0:86:93:69: + c1:f1:e0:cd:8f:df:cd:ef:33:31:a8:e1:93:cf:bd:13:13:66: + 55:ef:44:63:06:0a:11:7a:78:e7:5c:6f:d0:f9:9d:bf:90:e5: + f4:d1:54:31:b8:0d:ed:ed:c0:e2:63:5c:13:01:ff:a8:11:c5: + 7d:42:e1:94:63:6a:63:99:0f:82:ef:49:f7:93:92:e6:72:d7: + ed:88:d6:ab:b2:25:8c:37:8d:08:22:a0:80:9b:14:fb:a4:a2: + 4f:43:be:ff:d4:e9:7e:79 +-----BEGIN CERTIFICATE----- +MIIFEjCCAvqgAwIBAgIBBTANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMCAXDTE5MDMyMjIyMjUwNVoYDzI1 +MTgxMTIxMjIyNTA1WjAyMQswCQYDVQQGEwJTRTEjMCEGA1UEAwwaVGVzdCBjZXJ0 +IERpZ2l0YWxTaWduYXR1cmUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQDS5bYn92zB0LqKSmpOtaaSLluY1wxqfvS/GTAt7hxa7ij2XKgSAyDH6CuxRJ+3 +VCduF/zA9vfqONLId6tqrtGrnx5534pRVapsahN0dC/AIFfv8+Fx2rDsYumKAdr2 +5sZa/hFhWFygAewOr3ANcpSh1Bx2U645oM9w2Nl8lRgrXzYAL1y+otWODuOqdgwf +hrNp/uQpCjCxyoMa8oj8kS9YvqSgJYK/FrPKcAl+zyn5LlgLSjo8becFY9VTkO3u +lp6O16jvUIs3vdyI9RK8BE7k8+xdneZGFOHhaxWr9FL2EnauLadl7I+9kFFSTefP +uiMBeoWLIkGmmAjkMwDB4oKwssb0ajTGqdexzMYaC61pH4mv4GPNUck2fwjwMZfq +eLuuIUyqLTLeNgPPZPiKwMWzxPl5dHqL1ey/GYfJJQyZfVajk2iXw8wI+zfALMuH +8rRO/s6GaSuOw55AqbZDbta2PQhDJAlYja/SXRwOzbzjC7NLpWmoPNcH0H/XeMdc +pJ/horx2d4AlDoIrQx7kZ0lH2WVFV+1Z126hjXagwmVSyMhXXd200k8npQjxiH7S +Pl1gxmf7yRnneMxBbSQRzaTmz1aMQU2v1uIiwKNkLEsn9rOHnQjmKi/byFBXlaPP +Z3f4gBXzRQBH+IBuIbWA8YEpRT+piuISEk3EkOPaqwiAvQIDAQABozkwNzAJBgNV +HRMEAjAAMAsGA1UdDwQEAwIGwDAdBgNVHQ4EFgQUxETeNGxV8CEA9M/wVWeS+4+z +QEYwDQYJKoZIhvcNAQEFBQADggIBAKOcx7c9/I49W1iYsAVj/adQwtTowki4sKjj ++cKLEUehEV7oTXXFuNnsr4GVHuzY9oq2FxKr1DCEyzVqyFBeHFUmd+6E8ICSlcM3 +ULMjIXo7Y1oY5Ej83psmUDieL6OtA18MsKEOQQsBcbmi34T2xNadi/eo7cx+toxc +vCYMl3cV3PtmSw0B2Y5Yjhy/NUe4ENQS5YAJs9hK9Ao/ai+fRxaAp5Jq1Dt5eyW5 +PhSpkE6SbpJ7bwQ6DcZjd4LiLekkY86gsYwjHdt5uE93uH/SSV20YKB4u9bXVv8j +wfpGzZorDYfftZjrfv2vbp0D3tOX5xkJIBPOLrWJ8Eetsj3xXneL3dNu4qg8zWoi +oWOSjC7KCg2qLBWY3icI5e6l4OVUMCYvMqvD3uCCMirdOcs8dZWPnjc0NIAUJ6rG +idOPejUZO4vBVgZ2swwSBRD0WmL/1e/g+Nqq3CsUc60xyNoZ/lRRMg87fxMhDVxP +M+cHkjb9AQTU5ky63LR1wPYfPFpKNECHO4xEYN4RjRhBCuTp1hn1e49TPNg9fE/0 +sIaTacHx4M2P383vMzGo4ZPPvRMTZlXvRGMGChF6eOdcb9D5nb+Q5fTRVDG4De3t +wOJjXBMB/6gRxX1C4ZRjamOZD4LvSfeTkuZy1+2I1quyJYw3jQgioICbFPukok9D +vv/U6X55 +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/test-ds-only.key b/third_party/heimdal/lib/hx509/data/test-ds-only.key new file mode 100644 index 0000000..9129038 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test-ds-only.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +dDGZmYTPMav2jSUmg7BMOO1iyjFI0hg= +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/test-enveloped-aes-128 b/third_party/heimdal/lib/hx509/data/test-enveloped-aes-128 Binary files differnew file mode 100644 index 0000000..a75409b --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test-enveloped-aes-128 diff --git a/third_party/heimdal/lib/hx509/data/test-enveloped-aes-256 b/third_party/heimdal/lib/hx509/data/test-enveloped-aes-256 Binary files differnew file mode 100644 index 0000000..4fda391 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test-enveloped-aes-256 diff --git a/third_party/heimdal/lib/hx509/data/test-enveloped-des b/third_party/heimdal/lib/hx509/data/test-enveloped-des Binary files differnew file mode 100644 index 0000000..944da00 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test-enveloped-des diff --git a/third_party/heimdal/lib/hx509/data/test-enveloped-des-ede3 b/third_party/heimdal/lib/hx509/data/test-enveloped-des-ede3 Binary files differnew file mode 100644 index 0000000..c27dfbc --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test-enveloped-des-ede3 diff --git a/third_party/heimdal/lib/hx509/data/test-enveloped-rc2-128 b/third_party/heimdal/lib/hx509/data/test-enveloped-rc2-128 Binary files differnew file mode 100644 index 0000000..72f8158 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test-enveloped-rc2-128 diff --git a/third_party/heimdal/lib/hx509/data/test-enveloped-rc2-40 b/third_party/heimdal/lib/hx509/data/test-enveloped-rc2-40 Binary files differnew file mode 100644 index 0000000..0e5eb02 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test-enveloped-rc2-40 diff --git a/third_party/heimdal/lib/hx509/data/test-enveloped-rc2-64 b/third_party/heimdal/lib/hx509/data/test-enveloped-rc2-64 Binary files differnew file mode 100644 index 0000000..9ce6694 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test-enveloped-rc2-64 diff --git a/third_party/heimdal/lib/hx509/data/test-ke-only.crt b/third_party/heimdal/lib/hx509/data/test-ke-only.crt new file mode 100644 index 0000000..a6cc06a --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test-ke-only.crt @@ -0,0 +1,117 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4 (0x4) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Mar 22 22:25:04 2019 GMT + Not After : Nov 21 22:25:04 2518 GMT + Subject: C=SE, CN=Test cert KeyEncipherment + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:bf:5f:55:ca:c5:c6:c5:00:a6:40:17:fc:1f:a2: + c7:e7:41:1b:29:37:6e:ba:7c:01:19:f3:4a:d7:c4: + 9a:83:17:4d:40:cd:30:d1:9f:fd:94:49:41:5c:7a: + 2d:32:83:81:29:15:e3:b2:1f:06:1b:f5:f3:7f:91: + cf:dc:82:b1:4e:d5:a9:48:da:63:49:b8:b8:41:0d: + cf:eb:76:df:1a:33:5a:7b:2f:ed:13:5d:ce:77:85: + bc:1f:52:b4:ff:96:20:48:09:19:d7:0d:55:ed:a8: + 9f:de:bd:26:2a:cf:2c:f4:48:d3:eb:94:f1:b4:ca: + 5b:6d:1b:21:82:46:98:23:84:d7:be:08:90:54:f4: + 46:ef:59:6e:8b:8c:7f:65:90:5a:c3:fb:c4:1d:97: + 9e:1a:be:82:96:d7:86:5b:d7:1a:0e:04:1f:30:71: + 99:70:40:28:6c:b2:16:3c:19:f1:f3:9f:54:22:9c: + e0:e5:2b:c9:30:a1:01:cf:7e:1f:a2:40:d7:d3:ad: + 23:6d:fe:55:dc:ad:87:88:ee:e8:9b:81:e8:72:8d: + 2a:25:58:ff:81:18:f0:24:9a:13:31:f9:30:7c:ed: + f1:d5:4b:13:ce:bf:83:48:47:9c:44:99:0d:52:e7: + 52:4f:02:91:10:fe:77:39:f3:fc:ce:04:bf:57:4e: + 3b:17:a3:c2:94:85:10:d6:76:a2:c0:04:45:d1:ff: + 96:a7:c0:a8:39:bb:7a:4c:f4:96:4c:5f:2d:63:85: + 52:6e:74:5d:70:7a:de:35:7c:92:9f:ed:e6:85:c8: + f0:1d:b7:be:29:54:78:5e:7c:4a:a2:b8:85:ee:b7: + 20:2d:0c:78:a6:32:be:c0:a2:89:4f:f4:c8:e0:3c: + 3a:4c:b3:68:a1:a7:eb:b5:c7:21:74:b9:3d:0e:07: + 3f:ce:35:29:b5:33:1f:ac:d8:36:dd:d1:54:3d:47: + c9:29:c6:26:23:e8:51:8d:25:9a:8c:96:84:74:e9: + f0:10:d8:96:f5:ad:22:31:8f:e9:6a:a5:9b:3b:00: + 93:5e:80:22:f1:3a:e5:2d:10:7b:c6:a8:b9:6b:8f: + ab:33:64:99:fe:aa:77:7a:0f:96:f9:3f:fe:15:6d: + 8e:4a:95:a7:35:9b:f4:20:cb:a2:a1:d9:f6:62:6b: + a7:4e:b4:22:3d:22:73:f4:7e:0d:af:62:41:7a:d2: + 15:ab:b9:a2:25:a8:87:e0:b5:1b:be:c0:16:d1:e4: + 40:5b:56:a7:ab:39:d1:85:02:f5:4f:95:3f:37:dc: + 97:e4:89:c8:20:ab:11:9f:d8:f1:77:d6:b0:60:4f: + ab:f9:88:37:ef:9f:bc:2a:f3:22:3d:2e:21:82:63: + c6:21:73 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + FF:78:58:BD:A5:C2:4D:D1:07:04:05:DD:15:6A:A2:2C:92:EB:54:04 + Signature Algorithm: sha1WithRSAEncryption + 0d:b6:af:48:3b:0f:01:49:0b:12:d7:bc:9f:35:09:2a:42:e4: + d2:86:d2:c5:53:65:1b:a4:d5:52:87:28:dc:01:70:97:f3:0b: + 87:35:67:bb:b7:dd:f9:80:09:d3:84:33:11:2a:fe:0b:85:75: + 4b:d1:84:0c:46:35:d3:69:b8:fe:fc:a3:5a:c7:10:8c:2b:36: + c8:f0:ab:e7:f8:98:6c:b5:ec:1e:26:69:31:9b:07:29:03:ee: + 21:34:5c:52:1a:58:4a:c5:10:43:6b:8e:fc:9d:94:12:67:d0: + 12:40:55:14:f0:8f:d5:a7:a9:c7:d4:65:99:53:0d:3f:9a:23: + ab:13:ed:25:eb:33:56:b8:b3:ed:f5:6d:6b:a4:26:6c:80:6d: + 4c:27:8e:e5:5f:4d:e8:83:0b:c8:ca:17:6c:de:b9:af:ff:2f: + cb:9c:25:24:5f:09:e4:d9:62:a8:6e:de:da:c9:9e:1f:be:bf: + 19:1a:df:01:e2:dc:8c:ef:64:40:8e:b3:2a:0d:29:a9:7f:e7: + fa:bb:4b:76:41:c4:82:e7:07:d0:21:d5:1a:88:64:27:58:1a: + 8f:9e:48:e8:cb:40:d2:f0:ff:68:06:10:1b:5a:c3:1b:9f:48: + 52:b6:a0:8a:4c:0e:be:f3:e4:ed:a1:7a:9c:52:91:38:15:fc: + 92:ff:82:55:10:bd:d7:a2:1c:bb:e4:8c:56:d5:f6:c7:77:12: + 2f:cb:61:c6:75:a2:71:9c:4e:96:b3:0f:b6:d7:85:cb:52:0f: + 96:87:4a:05:15:ba:f7:31:b0:76:54:07:b8:59:38:5e:7a:03: + a4:87:60:e9:12:4d:aa:3a:98:d6:b9:46:a1:73:40:87:27:cf: + aa:87:66:e8:32:37:74:0c:93:ff:a9:ef:52:3b:a2:36:1e:16: + 1c:07:45:e9:65:9f:9e:de:ff:7b:b1:c4:a8:7e:59:25:79:1f: + da:7f:35:85:36:ea:cf:79:ff:71:96:77:28:3a:e6:af:68:f5: + 4c:c3:1a:20:7b:09:8d:66:15:b0:92:0a:4b:39:e4:f1:06:9e: + 9e:4e:f1:ca:bf:81:77:e7:00:82:79:26:0f:d1:f9:a2:4d:9a: + c8:7a:da:f6:d0:1e:65:04:02:2b:14:0b:84:45:eb:5d:6c:68: + 04:d7:a6:98:85:8c:fb:7e:de:42:63:68:5d:cd:a1:3d:4b:85: + 5e:e5:c3:38:a6:79:f4:02:5c:d0:ea:53:c6:91:84:08:b2:eb: + 2f:02:bb:5d:3b:bc:f2:e7:8d:67:44:70:0f:96:63:25:25:1a: + 38:1a:cc:a6:72:2d:41:23:8c:cc:95:12:4b:4f:64:91:21:79: + 96:46:70:8d:68:dc:dc:d5 +-----BEGIN CERTIFICATE----- +MIIFETCCAvmgAwIBAgIBBDANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMCAXDTE5MDMyMjIyMjUwNFoYDzI1 +MTgxMTIxMjIyNTA0WjAxMQswCQYDVQQGEwJTRTEiMCAGA1UEAwwZVGVzdCBjZXJ0 +IEtleUVuY2lwaGVybWVudDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +AL9fVcrFxsUApkAX/B+ix+dBGyk3brp8ARnzStfEmoMXTUDNMNGf/ZRJQVx6LTKD +gSkV47IfBhv183+Rz9yCsU7VqUjaY0m4uEENz+t23xozWnsv7RNdzneFvB9StP+W +IEgJGdcNVe2on969JirPLPRI0+uU8bTKW20bIYJGmCOE174IkFT0Ru9ZbouMf2WQ +WsP7xB2Xnhq+gpbXhlvXGg4EHzBxmXBAKGyyFjwZ8fOfVCKc4OUryTChAc9+H6JA +19OtI23+Vdyth4ju6JuB6HKNKiVY/4EY8CSaEzH5MHzt8dVLE86/g0hHnESZDVLn +Uk8CkRD+dznz/M4Ev1dOOxejwpSFENZ2osAERdH/lqfAqDm7ekz0lkxfLWOFUm50 +XXB63jV8kp/t5oXI8B23vilUeF58SqK4he63IC0MeKYyvsCiiU/0yOA8OkyzaKGn +67XHIXS5PQ4HP841KbUzH6zYNt3RVD1HySnGJiPoUY0lmoyWhHTp8BDYlvWtIjGP +6WqlmzsAk16AIvE65S0Qe8aouWuPqzNkmf6qd3oPlvk//hVtjkqVpzWb9CDLoqHZ +9mJrp060Ij0ic/R+Da9iQXrSFau5oiWoh+C1G77AFtHkQFtWp6s50YUC9U+VPzfc +l+SJyCCrEZ/Y8XfWsGBPq/mIN++fvCrzIj0uIYJjxiFzAgMBAAGjOTA3MAkGA1Ud +EwQCMAAwCwYDVR0PBAQDAgVgMB0GA1UdDgQWBBT/eFi9pcJN0QcEBd0VaqIskutU +BDANBgkqhkiG9w0BAQUFAAOCAgEADbavSDsPAUkLEte8nzUJKkLk0obSxVNlG6TV +Uoco3AFwl/MLhzVnu7fd+YAJ04QzESr+C4V1S9GEDEY102m4/vyjWscQjCs2yPCr +5/iYbLXsHiZpMZsHKQPuITRcUhpYSsUQQ2uO/J2UEmfQEkBVFPCP1aepx9RlmVMN +P5ojqxPtJeszVriz7fVta6QmbIBtTCeO5V9N6IMLyMoXbN65r/8vy5wlJF8J5Nli +qG7e2smeH76/GRrfAeLcjO9kQI6zKg0pqX/n+rtLdkHEgucH0CHVGohkJ1gaj55I +6MtA0vD/aAYQG1rDG59IUragikwOvvPk7aF6nFKROBX8kv+CVRC916Icu+SMVtX2 +x3cSL8thxnWicZxOlrMPtteFy1IPlodKBRW69zGwdlQHuFk4XnoDpIdg6RJNqjqY +1rlGoXNAhyfPqodm6DI3dAyT/6nvUjuiNh4WHAdF6WWfnt7/e7HEqH5ZJXkf2n81 +hTbqz3n/cZZ3KDrmr2j1TMMaIHsJjWYVsJIKSznk8Qaenk7xyr+Bd+cAgnkmD9H5 +ok2ayHra9tAeZQQCKxQLhEXrXWxoBNemmIWM+37eQmNoXc2hPUuFXuXDOKZ59AJc +0OpTxpGECLLrLwK7XTu88ueNZ0RwD5ZjJSUaOBrMpnItQSOMzJUSS09kkSF5lkZw +jWjc3NU= +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/test-ke-only.key b/third_party/heimdal/lib/hx509/data/test-ke-only.key new file mode 100644 index 0000000..1b463b9 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test-ke-only.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +hFXFVI1+i1ntO6Nf9NvTPVfjJNWzW7Y= +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/test-nopw.p12 b/third_party/heimdal/lib/hx509/data/test-nopw.p12 Binary files differnew file mode 100644 index 0000000..e94aa9a --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test-nopw.p12 diff --git a/third_party/heimdal/lib/hx509/data/test-pw.key b/third_party/heimdal/lib/hx509/data/test-pw.key new file mode 100644 index 0000000..495eef6 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test-pw.key @@ -0,0 +1,54 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,AE05E89E216F377B4B073A88DA8A284B + +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 +-----END RSA PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/test-signed-data b/third_party/heimdal/lib/hx509/data/test-signed-data Binary files differnew file mode 100644 index 0000000..1228c85 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test-signed-data diff --git a/third_party/heimdal/lib/hx509/data/test-signed-data-noattr b/third_party/heimdal/lib/hx509/data/test-signed-data-noattr Binary files differnew file mode 100644 index 0000000..f230779 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test-signed-data-noattr diff --git a/third_party/heimdal/lib/hx509/data/test-signed-data-noattr-nocerts b/third_party/heimdal/lib/hx509/data/test-signed-data-noattr-nocerts Binary files differnew file mode 100644 index 0000000..49fba9b --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test-signed-data-noattr-nocerts diff --git a/third_party/heimdal/lib/hx509/data/test-signed-sha-1 b/third_party/heimdal/lib/hx509/data/test-signed-sha-1 Binary files differnew file mode 100644 index 0000000..8ad1121 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test-signed-sha-1 diff --git a/third_party/heimdal/lib/hx509/data/test-signed-sha-256 b/third_party/heimdal/lib/hx509/data/test-signed-sha-256 Binary files differnew file mode 100644 index 0000000..1228c85 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test-signed-sha-256 diff --git a/third_party/heimdal/lib/hx509/data/test-signed-sha-512 b/third_party/heimdal/lib/hx509/data/test-signed-sha-512 Binary files differnew file mode 100644 index 0000000..1e40abe --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test-signed-sha-512 diff --git a/third_party/heimdal/lib/hx509/data/test.combined.crt b/third_party/heimdal/lib/hx509/data/test.combined.crt new file mode 100644 index 0000000..a07dbf1 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test.combined.crt @@ -0,0 +1,168 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Mar 22 22:25:02 2019 GMT + Not After : Nov 21 22:25:02 2518 GMT + Subject: C=SE, CN=Test cert + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:da:1d:4d:ca:51:9d:f1:9f:d7:a4:7a:45:f8:75: + 98:66:b2:c5:7d:53:de:42:35:74:81:cd:1e:9f:f3: + 43:d7:a7:83:7f:fb:a2:ce:3c:44:37:80:4f:21:36: + a6:f6:c9:51:74:9e:e2:9b:bf:ad:e4:eb:72:11:64: + 36:88:b3:a9:91:63:c7:ee:38:c4:f5:8c:06:71:e5: + 09:b7:eb:57:5d:bf:db:5b:72:07:c5:29:e8:6f:33: + b3:a2:27:ef:1f:50:f0:55:33:63:41:23:e0:b2:f7: + 21:77:4b:ab:9d:73:2a:bb:b6:4e:88:7f:7c:e5:c6: + 37:3e:b6:20:c1:57:3e:6d:57:78:ef:0d:47:e9:41: + e7:fa:b6:2d:32:3f:42:05:8d:56:af:f5:c4:b8:6e: + 99:1a:e7:07:d5:a1:3f:29:7d:ce:b2:39:a6:ab:06: + 7a:e2:26:39:d8:96:9e:3b:c8:af:79:3e:9a:24:4e: + 4b:b2:af:e4:07:0e:71:dc:2f:70:27:97:3c:a2:fa: + 69:9b:57:4b:c5:53:5e:28:0c:b0:c7:57:1f:a2:b2: + 26:0f:5f:bf:d3:45:78:90:5a:2c:fc:6a:67:33:b6: + c1:7e:cd:17:c0:58:9e:ba:85:c5:15:5a:5a:67:db: + bf:2f:05:cd:38:d9:94:c9:95:7f:9b:68:b0:62:ff: + 37:92:cf:d8:77:be:cb:72:3d:0f:b9:80:44:57:c0: + c9:10:01:fd:07:25:30:eb:d8:48:05:af:98:fa:c4: + 64:6d:59:a6:6a:8d:1b:d4:4b:f3:07:98:68:e3:bb: + 59:c9:21:f8:11:b4:a2:82:1b:0d:e8:8c:e0:a5:e1: + 1c:71:ca:c3:2d:90:43:c3:ee:99:2c:7d:41:48:39: + c8:00:72:0d:80:39:23:a1:3a:27:ed:07:ca:32:8f: + 34:ca:bb:9d:67:13:7d:31:ed:4a:db:35:7a:ce:b3: + 89:e3:64:9d:3e:47:4e:d3:b7:bd:ab:12:16:10:bb: + 66:e8:1a:77:4c:2a:e0:b9:16:69:66:14:83:4e:4a: + f3:6f:ab:85:6a:70:c6:9b:ce:93:ab:75:36:a3:a5: + aa:9f:45:d6:a2:7f:17:c7:6f:f9:f5:e7:35:51:a5: + 75:c5:07:be:26:ce:7b:3f:29:3a:74:6b:17:79:4e: + cf:4c:0a:69:75:58:db:eb:a8:dd:f1:e6:cc:a3:18: + 53:a5:c5:a5:5a:a1:cf:37:6a:b1:9f:d3:d4:eb:0f: + 02:40:d2:ae:68:ce:bc:c5:46:e3:ee:f8:97:88:ee: + c8:a7:01:7a:a1:23:af:f3:31:2c:2a:6f:12:77:dc: + 3c:51:9d:40:f4:9a:2a:7b:85:29:1f:3e:c3:d5:37: + 8e:6e:09 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 1B:F4:EC:34:42:BA:8B:67:AC:55:F2:37:5D:B4:68:A9:D8:5E:58:7B + Signature Algorithm: sha1WithRSAEncryption + 95:f7:1c:99:72:42:4f:d3:bd:ba:3f:7a:75:bb:01:3a:ad:ce: + 6b:7b:b7:3d:5d:3b:46:51:ea:9a:36:94:70:36:1c:3b:fc:ba: + 9d:8b:0d:44:36:08:ad:a6:73:82:bc:23:ed:f9:5a:09:8f:9d: + 62:11:c1:94:7c:61:66:1f:8b:b9:0a:dc:3a:b5:eb:22:54:de: + a3:e5:8a:94:10:1f:84:52:6d:fe:27:c8:e5:cb:a5:8e:a9:83: + 16:95:0d:6c:3e:57:85:e1:ec:82:05:47:6d:28:ad:0d:84:fa: + 40:a0:96:f4:84:aa:d1:e1:0b:b7:91:e2:47:4f:05:97:f8:10: + a0:e8:57:bd:ed:48:65:55:75:da:e5:34:e8:f1:20:95:d6:40: + 8c:42:bf:b4:d9:55:c8:30:e8:d5:ce:d8:1d:30:65:90:39:eb: + e2:83:ed:11:03:cd:07:c0:e1:c4:91:84:a0:97:8e:6d:22:e6: + 75:77:21:7c:32:8b:48:ed:d6:b2:19:2e:af:26:ad:7d:6c:ce: + 09:e1:78:b6:72:61:60:22:92:b8:df:42:6b:34:6b:5f:35:ef: + f1:d3:c6:7f:92:05:3c:d0:08:77:01:66:f7:57:b8:65:de:d3: + d2:b1:bf:93:b1:8c:a3:27:e6:d4:e2:2b:9b:cd:9d:be:31:82: + 5b:53:dd:5a:bd:39:05:5f:8c:56:f2:7f:9b:b7:ef:e6:07:96: + bf:8a:d9:8d:bb:62:98:86:de:aa:91:c3:fe:e7:bb:a7:1f:f0: + fd:1f:6c:a6:04:04:f0:c2:51:a1:91:8c:9a:ee:f9:87:42:37: + 7e:9c:27:72:59:dc:60:a8:8e:d1:81:97:f1:15:c3:d8:a9:4e: + 9a:09:e9:81:76:39:36:b3:08:a1:e5:5e:97:37:ba:43:8f:06: + 1a:70:69:3b:fe:79:a6:5e:2d:26:04:e9:bc:5f:57:c9:d0:80: + c2:0d:4b:c7:0e:dd:04:e5:15:49:9d:d7:ff:ee:a3:1c:04:56: + 7d:e2:a0:d3:39:1a:59:bd:85:b0:eb:54:ea:81:8b:e1:17:94: + a5:fe:e3:0c:d0:74:42:ee:4a:f4:66:90:49:4b:64:bc:47:35: + f5:b2:60:8e:74:05:d0:a6:d2:94:b4:e0:0f:4b:3f:35:ea:2a: + e0:24:58:c1:6e:d0:65:6e:58:f7:e1:90:02:ae:40:23:25:e9: + 80:9a:d2:a7:ea:5d:fc:6d:f8:45:0f:db:53:91:55:32:46:e3: + 6a:c0:54:0a:5a:4c:e8:1a:1e:a6:33:3e:fe:ed:b6:ad:cf:6a: + 3c:2f:b2:6c:47:75:f1:29:43:31:69:c3:0c:42:56:5b:d9:b8: + 99:7b:ff:2b:50:87:34:2e +-----BEGIN CERTIFICATE----- +MIIFATCCAumgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMCAXDTE5MDMyMjIyMjUwMloYDzI1 +MTgxMTIxMjIyNTAyWjAhMQswCQYDVQQGEwJTRTESMBAGA1UEAwwJVGVzdCBjZXJ0 +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2h1NylGd8Z/XpHpF+HWY +ZrLFfVPeQjV0gc0en/ND16eDf/uizjxEN4BPITam9slRdJ7im7+t5OtyEWQ2iLOp +kWPH7jjE9YwGceUJt+tXXb/bW3IHxSnobzOzoifvH1DwVTNjQSPgsvchd0urnXMq +u7ZOiH985cY3PrYgwVc+bVd47w1H6UHn+rYtMj9CBY1Wr/XEuG6ZGucH1aE/KX3O +sjmmqwZ64iY52JaeO8iveT6aJE5Lsq/kBw5x3C9wJ5c8ovppm1dLxVNeKAywx1cf +orImD1+/00V4kFos/GpnM7bBfs0XwFieuoXFFVpaZ9u/LwXNONmUyZV/m2iwYv83 +ks/Yd77Lcj0PuYBEV8DJEAH9ByUw69hIBa+Y+sRkbVmmao0b1EvzB5ho47tZySH4 +EbSighsN6IzgpeEcccrDLZBDw+6ZLH1BSDnIAHINgDkjoTon7QfKMo80yrudZxN9 +Me1K2zV6zrOJ42SdPkdO07e9qxIWELtm6Bp3TCrguRZpZhSDTkrzb6uFanDGm86T +q3U2o6Wqn0XWon8Xx2/59ec1UaV1xQe+Js57Pyk6dGsXeU7PTAppdVjb66jd8ebM +oxhTpcWlWqHPN2qxn9PU6w8CQNKuaM68xUbj7viXiO7IpwF6oSOv8zEsKm8Sd9w8 +UZ1A9Joqe4UpHz7D1TeObgkCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMC +BeAwHQYDVR0OBBYEFBv07DRCuotnrFXyN120aKnYXlh7MA0GCSqGSIb3DQEBBQUA +A4ICAQCV9xyZckJP0726P3p1uwE6rc5re7c9XTtGUeqaNpRwNhw7/Lqdiw1ENgit +pnOCvCPt+VoJj51iEcGUfGFmH4u5Ctw6tesiVN6j5YqUEB+EUm3+J8jly6WOqYMW +lQ1sPleF4eyCBUdtKK0NhPpAoJb0hKrR4Qu3keJHTwWX+BCg6Fe97UhlVXXa5TTo +8SCV1kCMQr+02VXIMOjVztgdMGWQOevig+0RA80HwOHEkYSgl45tIuZ1dyF8MotI +7dayGS6vJq19bM4J4Xi2cmFgIpK430JrNGtfNe/x08Z/kgU80Ah3AWb3V7hl3tPS +sb+TsYyjJ+bU4iubzZ2+MYJbU91avTkFX4xW8n+bt+/mB5a/itmNu2KYht6qkcP+ +57unH/D9H2ymBATwwlGhkYya7vmHQjd+nCdyWdxgqI7RgZfxFcPYqU6aCemBdjk2 +swih5V6XN7pDjwYacGk7/nmmXi0mBOm8X1fJ0IDCDUvHDt0E5RVJndf/7qMcBFZ9 +4qDTORpZvYWw61TqgYvhF5Sl/uMM0HRC7kr0ZpBJS2S8RzX1smCOdAXQptKUtOAP +Sz816irgJFjBbtBlblj34ZACrkAjJemAmtKn6l38bfhFD9tTkVUyRuNqwFQKWkzo +Gh6mMz7+7batz2o8L7JsR3XxKUMxacMMQlZb2biZe/8rUIc0Lg== +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +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 +UK2bY3PmI10F5vBYLQpLlCYUyBDf +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/test.crt b/third_party/heimdal/lib/hx509/data/test.crt new file mode 100644 index 0000000..40663c4 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test.crt @@ -0,0 +1,116 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Mar 22 22:25:02 2019 GMT + Not After : Nov 21 22:25:02 2518 GMT + Subject: C=SE, CN=Test cert + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (4096 bit) + Modulus: + 00:da:1d:4d:ca:51:9d:f1:9f:d7:a4:7a:45:f8:75: + 98:66:b2:c5:7d:53:de:42:35:74:81:cd:1e:9f:f3: + 43:d7:a7:83:7f:fb:a2:ce:3c:44:37:80:4f:21:36: + a6:f6:c9:51:74:9e:e2:9b:bf:ad:e4:eb:72:11:64: + 36:88:b3:a9:91:63:c7:ee:38:c4:f5:8c:06:71:e5: + 09:b7:eb:57:5d:bf:db:5b:72:07:c5:29:e8:6f:33: + b3:a2:27:ef:1f:50:f0:55:33:63:41:23:e0:b2:f7: + 21:77:4b:ab:9d:73:2a:bb:b6:4e:88:7f:7c:e5:c6: + 37:3e:b6:20:c1:57:3e:6d:57:78:ef:0d:47:e9:41: + e7:fa:b6:2d:32:3f:42:05:8d:56:af:f5:c4:b8:6e: + 99:1a:e7:07:d5:a1:3f:29:7d:ce:b2:39:a6:ab:06: + 7a:e2:26:39:d8:96:9e:3b:c8:af:79:3e:9a:24:4e: + 4b:b2:af:e4:07:0e:71:dc:2f:70:27:97:3c:a2:fa: + 69:9b:57:4b:c5:53:5e:28:0c:b0:c7:57:1f:a2:b2: + 26:0f:5f:bf:d3:45:78:90:5a:2c:fc:6a:67:33:b6: + c1:7e:cd:17:c0:58:9e:ba:85:c5:15:5a:5a:67:db: + bf:2f:05:cd:38:d9:94:c9:95:7f:9b:68:b0:62:ff: + 37:92:cf:d8:77:be:cb:72:3d:0f:b9:80:44:57:c0: + c9:10:01:fd:07:25:30:eb:d8:48:05:af:98:fa:c4: + 64:6d:59:a6:6a:8d:1b:d4:4b:f3:07:98:68:e3:bb: + 59:c9:21:f8:11:b4:a2:82:1b:0d:e8:8c:e0:a5:e1: + 1c:71:ca:c3:2d:90:43:c3:ee:99:2c:7d:41:48:39: + c8:00:72:0d:80:39:23:a1:3a:27:ed:07:ca:32:8f: + 34:ca:bb:9d:67:13:7d:31:ed:4a:db:35:7a:ce:b3: + 89:e3:64:9d:3e:47:4e:d3:b7:bd:ab:12:16:10:bb: + 66:e8:1a:77:4c:2a:e0:b9:16:69:66:14:83:4e:4a: + f3:6f:ab:85:6a:70:c6:9b:ce:93:ab:75:36:a3:a5: + aa:9f:45:d6:a2:7f:17:c7:6f:f9:f5:e7:35:51:a5: + 75:c5:07:be:26:ce:7b:3f:29:3a:74:6b:17:79:4e: + cf:4c:0a:69:75:58:db:eb:a8:dd:f1:e6:cc:a3:18: + 53:a5:c5:a5:5a:a1:cf:37:6a:b1:9f:d3:d4:eb:0f: + 02:40:d2:ae:68:ce:bc:c5:46:e3:ee:f8:97:88:ee: + c8:a7:01:7a:a1:23:af:f3:31:2c:2a:6f:12:77:dc: + 3c:51:9d:40:f4:9a:2a:7b:85:29:1f:3e:c3:d5:37: + 8e:6e:09 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 1B:F4:EC:34:42:BA:8B:67:AC:55:F2:37:5D:B4:68:A9:D8:5E:58:7B + Signature Algorithm: sha1WithRSAEncryption + 95:f7:1c:99:72:42:4f:d3:bd:ba:3f:7a:75:bb:01:3a:ad:ce: + 6b:7b:b7:3d:5d:3b:46:51:ea:9a:36:94:70:36:1c:3b:fc:ba: + 9d:8b:0d:44:36:08:ad:a6:73:82:bc:23:ed:f9:5a:09:8f:9d: + 62:11:c1:94:7c:61:66:1f:8b:b9:0a:dc:3a:b5:eb:22:54:de: + a3:e5:8a:94:10:1f:84:52:6d:fe:27:c8:e5:cb:a5:8e:a9:83: + 16:95:0d:6c:3e:57:85:e1:ec:82:05:47:6d:28:ad:0d:84:fa: + 40:a0:96:f4:84:aa:d1:e1:0b:b7:91:e2:47:4f:05:97:f8:10: + a0:e8:57:bd:ed:48:65:55:75:da:e5:34:e8:f1:20:95:d6:40: + 8c:42:bf:b4:d9:55:c8:30:e8:d5:ce:d8:1d:30:65:90:39:eb: + e2:83:ed:11:03:cd:07:c0:e1:c4:91:84:a0:97:8e:6d:22:e6: + 75:77:21:7c:32:8b:48:ed:d6:b2:19:2e:af:26:ad:7d:6c:ce: + 09:e1:78:b6:72:61:60:22:92:b8:df:42:6b:34:6b:5f:35:ef: + f1:d3:c6:7f:92:05:3c:d0:08:77:01:66:f7:57:b8:65:de:d3: + d2:b1:bf:93:b1:8c:a3:27:e6:d4:e2:2b:9b:cd:9d:be:31:82: + 5b:53:dd:5a:bd:39:05:5f:8c:56:f2:7f:9b:b7:ef:e6:07:96: + bf:8a:d9:8d:bb:62:98:86:de:aa:91:c3:fe:e7:bb:a7:1f:f0: + fd:1f:6c:a6:04:04:f0:c2:51:a1:91:8c:9a:ee:f9:87:42:37: + 7e:9c:27:72:59:dc:60:a8:8e:d1:81:97:f1:15:c3:d8:a9:4e: + 9a:09:e9:81:76:39:36:b3:08:a1:e5:5e:97:37:ba:43:8f:06: + 1a:70:69:3b:fe:79:a6:5e:2d:26:04:e9:bc:5f:57:c9:d0:80: + c2:0d:4b:c7:0e:dd:04:e5:15:49:9d:d7:ff:ee:a3:1c:04:56: + 7d:e2:a0:d3:39:1a:59:bd:85:b0:eb:54:ea:81:8b:e1:17:94: + a5:fe:e3:0c:d0:74:42:ee:4a:f4:66:90:49:4b:64:bc:47:35: + f5:b2:60:8e:74:05:d0:a6:d2:94:b4:e0:0f:4b:3f:35:ea:2a: + e0:24:58:c1:6e:d0:65:6e:58:f7:e1:90:02:ae:40:23:25:e9: + 80:9a:d2:a7:ea:5d:fc:6d:f8:45:0f:db:53:91:55:32:46:e3: + 6a:c0:54:0a:5a:4c:e8:1a:1e:a6:33:3e:fe:ed:b6:ad:cf:6a: + 3c:2f:b2:6c:47:75:f1:29:43:31:69:c3:0c:42:56:5b:d9:b8: + 99:7b:ff:2b:50:87:34:2e +-----BEGIN CERTIFICATE----- +MIIFATCCAumgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMCAXDTE5MDMyMjIyMjUwMloYDzI1 +MTgxMTIxMjIyNTAyWjAhMQswCQYDVQQGEwJTRTESMBAGA1UEAwwJVGVzdCBjZXJ0 +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2h1NylGd8Z/XpHpF+HWY +ZrLFfVPeQjV0gc0en/ND16eDf/uizjxEN4BPITam9slRdJ7im7+t5OtyEWQ2iLOp +kWPH7jjE9YwGceUJt+tXXb/bW3IHxSnobzOzoifvH1DwVTNjQSPgsvchd0urnXMq +u7ZOiH985cY3PrYgwVc+bVd47w1H6UHn+rYtMj9CBY1Wr/XEuG6ZGucH1aE/KX3O +sjmmqwZ64iY52JaeO8iveT6aJE5Lsq/kBw5x3C9wJ5c8ovppm1dLxVNeKAywx1cf +orImD1+/00V4kFos/GpnM7bBfs0XwFieuoXFFVpaZ9u/LwXNONmUyZV/m2iwYv83 +ks/Yd77Lcj0PuYBEV8DJEAH9ByUw69hIBa+Y+sRkbVmmao0b1EvzB5ho47tZySH4 +EbSighsN6IzgpeEcccrDLZBDw+6ZLH1BSDnIAHINgDkjoTon7QfKMo80yrudZxN9 +Me1K2zV6zrOJ42SdPkdO07e9qxIWELtm6Bp3TCrguRZpZhSDTkrzb6uFanDGm86T +q3U2o6Wqn0XWon8Xx2/59ec1UaV1xQe+Js57Pyk6dGsXeU7PTAppdVjb66jd8ebM +oxhTpcWlWqHPN2qxn9PU6w8CQNKuaM68xUbj7viXiO7IpwF6oSOv8zEsKm8Sd9w8 +UZ1A9Joqe4UpHz7D1TeObgkCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMC +BeAwHQYDVR0OBBYEFBv07DRCuotnrFXyN120aKnYXlh7MA0GCSqGSIb3DQEBBQUA +A4ICAQCV9xyZckJP0726P3p1uwE6rc5re7c9XTtGUeqaNpRwNhw7/Lqdiw1ENgit +pnOCvCPt+VoJj51iEcGUfGFmH4u5Ctw6tesiVN6j5YqUEB+EUm3+J8jly6WOqYMW +lQ1sPleF4eyCBUdtKK0NhPpAoJb0hKrR4Qu3keJHTwWX+BCg6Fe97UhlVXXa5TTo +8SCV1kCMQr+02VXIMOjVztgdMGWQOevig+0RA80HwOHEkYSgl45tIuZ1dyF8MotI +7dayGS6vJq19bM4J4Xi2cmFgIpK430JrNGtfNe/x08Z/kgU80Ah3AWb3V7hl3tPS +sb+TsYyjJ+bU4iubzZ2+MYJbU91avTkFX4xW8n+bt+/mB5a/itmNu2KYht6qkcP+ +57unH/D9H2ymBATwwlGhkYya7vmHQjd+nCdyWdxgqI7RgZfxFcPYqU6aCemBdjk2 +swih5V6XN7pDjwYacGk7/nmmXi0mBOm8X1fJ0IDCDUvHDt0E5RVJndf/7qMcBFZ9 +4qDTORpZvYWw61TqgYvhF5Sl/uMM0HRC7kr0ZpBJS2S8RzX1smCOdAXQptKUtOAP +Sz816irgJFjBbtBlblj34ZACrkAjJemAmtKn6l38bfhFD9tTkVUyRuNqwFQKWkzo +Gh6mMz7+7batz2o8L7JsR3XxKUMxacMMQlZb2biZe/8rUIc0Lg== +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/test.key b/third_party/heimdal/lib/hx509/data/test.key new file mode 100644 index 0000000..03de157 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +UK2bY3PmI10F5vBYLQpLlCYUyBDf +-----END PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/data/test.p12 b/third_party/heimdal/lib/hx509/data/test.p12 Binary files differnew file mode 100644 index 0000000..32d9c81 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/test.p12 diff --git a/third_party/heimdal/lib/hx509/data/win-u16-in-printablestring.der b/third_party/heimdal/lib/hx509/data/win-u16-in-printablestring.der Binary files differnew file mode 100644 index 0000000..5f6178f --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/win-u16-in-printablestring.der diff --git a/third_party/heimdal/lib/hx509/data/yutaka-pad-broken-ca.pem b/third_party/heimdal/lib/hx509/data/yutaka-pad-broken-ca.pem new file mode 100644 index 0000000..32685d1 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/yutaka-pad-broken-ca.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICijCCAfOgAwIBAgIJAOSnzE4Qx2H+MA0GCSqGSIb3DQEBBQUAMDkxCzAJBgNV +BAYTAkpQMRQwEgYDVQQKEwtDQSBURVNUIDEtNDEUMBIGA1UEAxMLQ0EgVEVTVCAx +LTQwHhcNMDYwOTA3MTYzMzE4WhcNMDYxMDA3MTYzMzE4WjA5MQswCQYDVQQGEwJK +UDEUMBIGA1UEChMLQ0EgVEVTVCAxLTQxFDASBgNVBAMTC0NBIFRFU1QgMS00MIGd +MA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDZfFjkPDZeorxWqk7/DKM2d/9Nao28 +dM6T5sb5L41hD5C1kXV6MJev5ALASSxtI6OVOmZO4gfubnsvcj0NTZO4SeF1yL1r +VDPdx7juQI1cbDiG/EwIMW29UIdj9h052JTmEbpT0RuP/4JWmAWrdO5UE40xua7S +z2/6+DB2ZklFoQIBA6OBmzCBmDAdBgNVHQ4EFgQU340JbeYcg6V9zi8aozy48aIh +tfgwaQYDVR0jBGIwYIAU340JbeYcg6V9zi8aozy48aIhtfihPaQ7MDkxCzAJBgNV +BAYTAkpQMRQwEgYDVQQKEwtDQSBURVNUIDEtNDEUMBIGA1UEAxMLQ0EgVEVTVCAx +LTSCCQDkp8xOEMdh/jAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBABsH +aJ/c/3cGHssi8IvVRci/aavqj607y7l22nKDtG1p4KAjnfNhBMOhRhFv00nJnokK +y0uc4DIegAW1bxQjqcMNNEmGbzAeixH/cRCot8C1LobEQmxNWCY2DJLWoI3wwqr8 +uUSnI1CDZ5402etkCiNXsDy/eYDrF+2KonkIWRrr +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/yutaka-pad-broken-cert.pem b/third_party/heimdal/lib/hx509/data/yutaka-pad-broken-cert.pem new file mode 100644 index 0000000..b0726ea --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/yutaka-pad-broken-cert.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIICzTCCAjagAwIBAgIJAOSnzE4Qx2H/MA0GCSqGSIb3DQEBBQUAMDkxCzAJBgNV +BAYTAkpQMRQwEgYDVQQKEwtDQSBURVNUIDEtNDEUMBIGA1UEAxMLQ0EgVEVTVCAx +LTQwHhcNMDYwOTA3MTY0MDM3WhcNMDcwOTA3MTY0MDM3WjBPMQswCQYDVQQGEwJK +UDEOMAwGA1UECBMFVG9reW8xFjAUBgNVBAoTDVRFU1QgMiBDTElFTlQxGDAWBgNV +BAMTD3d3dzIuZXhhbXBsZS5qcDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA +vSpZ6ig9DpeKB60h7ii1RitNuvkn4INOfEXjCjPSFwmIbGJqnyWvKTiMKzguEYkG +6CZAbsx44t3kvsVDeUd5WZBRgMoeQd1tNJBU4BXxOA8bVzdwstzaPeeufQtZDvKf +M4ej+fo/j9lYH9udCug1huaNybcCtijzGonkddX4JEUCAwEAAaOBxjCBwzAJBgNV +HRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZp +Y2F0ZTAdBgNVHQ4EFgQUK0DZtd8K1P2ij9gVKUNcHlx7uCIwaQYDVR0jBGIwYIAU +340JbeYcg6V9zi8aozy48aIhtfihPaQ7MDkxCzAJBgNVBAYTAkpQMRQwEgYDVQQK +EwtDQSBURVNUIDEtNDEUMBIGA1UEAxMLQ0EgVEVTVCAxLTSCCQDkp8xOEMdh/jAN +BgkqhkiG9w0BAQUFAAOBgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAUKJ+eFJYSvXwGF2wxzDXj+x5YCItrHFmrEy4AXXAW+H0NgJVNvqRY/O +Kw== +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/yutaka-pad-ok-ca.pem b/third_party/heimdal/lib/hx509/data/yutaka-pad-ok-ca.pem new file mode 100644 index 0000000..32685d1 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/yutaka-pad-ok-ca.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICijCCAfOgAwIBAgIJAOSnzE4Qx2H+MA0GCSqGSIb3DQEBBQUAMDkxCzAJBgNV +BAYTAkpQMRQwEgYDVQQKEwtDQSBURVNUIDEtNDEUMBIGA1UEAxMLQ0EgVEVTVCAx +LTQwHhcNMDYwOTA3MTYzMzE4WhcNMDYxMDA3MTYzMzE4WjA5MQswCQYDVQQGEwJK +UDEUMBIGA1UEChMLQ0EgVEVTVCAxLTQxFDASBgNVBAMTC0NBIFRFU1QgMS00MIGd +MA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDZfFjkPDZeorxWqk7/DKM2d/9Nao28 +dM6T5sb5L41hD5C1kXV6MJev5ALASSxtI6OVOmZO4gfubnsvcj0NTZO4SeF1yL1r +VDPdx7juQI1cbDiG/EwIMW29UIdj9h052JTmEbpT0RuP/4JWmAWrdO5UE40xua7S +z2/6+DB2ZklFoQIBA6OBmzCBmDAdBgNVHQ4EFgQU340JbeYcg6V9zi8aozy48aIh +tfgwaQYDVR0jBGIwYIAU340JbeYcg6V9zi8aozy48aIhtfihPaQ7MDkxCzAJBgNV +BAYTAkpQMRQwEgYDVQQKEwtDQSBURVNUIDEtNDEUMBIGA1UEAxMLQ0EgVEVTVCAx +LTSCCQDkp8xOEMdh/jAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBABsH +aJ/c/3cGHssi8IvVRci/aavqj607y7l22nKDtG1p4KAjnfNhBMOhRhFv00nJnokK +y0uc4DIegAW1bxQjqcMNNEmGbzAeixH/cRCot8C1LobEQmxNWCY2DJLWoI3wwqr8 +uUSnI1CDZ5402etkCiNXsDy/eYDrF+2KonkIWRrr +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/yutaka-pad-ok-cert.pem b/third_party/heimdal/lib/hx509/data/yutaka-pad-ok-cert.pem new file mode 100644 index 0000000..9a89e59 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/yutaka-pad-ok-cert.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIICzTCCAjagAwIBAgIJAOSnzE4Qx2H/MA0GCSqGSIb3DQEBBQUAMDkxCzAJBgNV +BAYTAkpQMRQwEgYDVQQKEwtDQSBURVNUIDEtNDEUMBIGA1UEAxMLQ0EgVEVTVCAx +LTQwHhcNMDYwOTA3MTY0MDM3WhcNMDcwOTA3MTY0MDM3WjBPMQswCQYDVQQGEwJK +UDEOMAwGA1UECBMFVG9reW8xFjAUBgNVBAoTDVRFU1QgMiBDTElFTlQxGDAWBgNV +BAMTD3d3dzIuZXhhbXBsZS5qcDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA +vSpZ6ig9DpeKB60h7ii1RitNuvkn4INOfEXjCjPSFwmIbGJqnyWvKTiMKzguEYkG +6CZAbsx44t3kvsVDeUd5WZBRgMoeQd1tNJBU4BXxOA8bVzdwstzaPeeufQtZDvKf +M4ej+fo/j9lYH9udCug1huaNybcCtijzGonkddX4JEUCAwEAAaOBxjCBwzAJBgNV +HRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZp +Y2F0ZTAdBgNVHQ4EFgQUK0DZtd8K1P2ij9gVKUNcHlx7uCIwaQYDVR0jBGIwYIAU +340JbeYcg6V9zi8aozy48aIhtfihPaQ7MDkxCzAJBgNVBAYTAkpQMRQwEgYDVQQK +EwtDQSBURVNUIDEtNDEUMBIGA1UEAxMLQ0EgVEVTVCAxLTSCCQDkp8xOEMdh/jAN +BgkqhkiG9w0BAQUFAAOBgQCkGhwCDLRwWbDnDFReXkIZ1/9OhfiR8yL1idP9iYVU +cSoWxSHPBWkv6LORFS03APcXCSzDPJ9pxTjFjGGFSI91fNrzkKdHU/+0WCF2uTh7 +Dz2blqtcmnJqMSn1xHxxfM/9e6M3XwFUMf7SGiKRAbDfsauPafEPTn83vSeKj1lg +Dw== +-----END CERTIFICATE----- diff --git a/third_party/heimdal/lib/hx509/data/yutaka-pad.key b/third_party/heimdal/lib/hx509/data/yutaka-pad.key new file mode 100644 index 0000000..1763623 --- /dev/null +++ b/third_party/heimdal/lib/hx509/data/yutaka-pad.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQC9KlnqKD0Ol4oHrSHuKLVGK026+Sfgg058ReMKM9IXCYhsYmqf +Ja8pOIwrOC4RiQboJkBuzHji3eS+xUN5R3lZkFGAyh5B3W00kFTgFfE4DxtXN3Cy +3No95659C1kO8p8zh6P5+j+P2Vgf250K6DWG5o3JtwK2KPMaieR11fgkRQIDAQAB +AoGBAJCYvwJun713uNsFTNpv46EvmMtDiWfk9ymnglVaJ03Uy6ON11Kvy6UGxJ6E +4zIkPFNYaghH5GAGncP1pg4exHKRGJTNcQbMf9iOsCTOuvKSWbBZpnJcFllKyESK +PTt72D6x/cuzDXVTeWvQMoOILa09szW7aqFNIdxae4Vq7a4BAkEA6MoehuRtZ4N9 +Jtc9cIpSKOOatZ1UajWEFV2yVHaDED2kkWxKjppPzRn06LzX8LWm1RT0qe3Zyasi +iXCXlno/+QJBANAGvY+k/+OvzWnv1yTKO8OmrMqkSzh3KAhFbiVWdQaqMSCWtKYk +GoOKnq0PB73ExhdbTFmxC4KBPHTC2guOca0CQCD78pNebnoKUYNdYCFAGCAfD97H +6hwadRqp6gi5uhxk/5pzY6UNDF2dXexURayfsIHktD4Xq5I9o2kiAPibXdECQQDC +KihwlL9K02JVSMl0y1XxDfclxSd4cq9o2PUv4HymVeA43LGMiRI+SPpF6Ut+ctW6 +IzsmVDu7+chl6yD9vFyZAkA3Auv9UxKL3kPtvu5G/lrCVmwzVfAzuwtnmSfp1+M5 +yTYBz+VFSsYrdlDZ3jdLnFzVOMiIm9pZca/L93QjmXJ+ +-----END RSA PRIVATE KEY----- diff --git a/third_party/heimdal/lib/hx509/doxygen.c b/third_party/heimdal/lib/hx509/doxygen.c new file mode 100644 index 0000000..a6d3d9c --- /dev/null +++ b/third_party/heimdal/lib/hx509/doxygen.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** @mainpage Heimdal PKIX/X.509 library + * + * @section intro Introduction + * + * Heimdal libhx509 library is a implementation of the PKIX/X.509 and + * related protocols. + * + * PKIX/X.509 is ... + * + * + * Sections in this manual are: + * - @ref page_name + * - @ref page_cert + * - @ref page_keyset + * - @ref page_error + * - @ref page_lock + * - @ref page_cms + * - @ref page_ca + * - @ref page_revoke + * - @ref page_print + * - @ref page_env + * + * The project web page: + * http://www.h5l.org/ + * + */ + +/** @defgroup hx509 hx509 library */ + +/** @defgroup hx509_error hx509 error functions + * See the @ref page_error for description and examples. */ +/** @defgroup hx509_cert hx509 certificate functions + * See the @ref page_cert for description and examples. */ +/** @defgroup hx509_keyset hx509 certificate store functions + * See the @ref page_keyset for description and examples. */ +/** @defgroup hx509_cms hx509 CMS/pkcs7 functions + * See the @ref page_cms for description and examples. */ +/** @defgroup hx509_crypto hx509 crypto functions */ +/** @defgroup hx509_misc hx509 misc functions */ +/** @defgroup hx509_name hx509 name functions + * See the @ref page_name for description and examples. */ +/** @defgroup hx509_revoke hx509 revokation checking functions + * See the @ref page_revoke for description and examples. */ +/** @defgroup hx509_verify hx509 verification functions */ +/** @defgroup hx509_lock hx509 lock functions + * See the @ref page_lock for description and examples. */ +/** @defgroup hx509_query hx509 query functions */ +/** @defgroup hx509_ca hx509 CA functions + * See the @ref page_ca for description and examples. */ +/** @defgroup hx509_peer hx509 certificate selecting functions */ +/** @defgroup hx509_print hx509 printing functions */ +/** @defgroup hx509_env hx509 environment functions */ diff --git a/third_party/heimdal/lib/hx509/env.c b/third_party/heimdal/lib/hx509/env.c new file mode 100644 index 0000000..7970438 --- /dev/null +++ b/third_party/heimdal/lib/hx509/env.c @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2007 - 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" + +/** + * @page page_env Hx509 environment functions + * + * See the library functions here: @ref hx509_env + */ + +/** + * Add a new key/value pair to the hx509_env. + * + * @param context A hx509 context. + * @param env environment to add the environment variable too. + * @param key key to add + * @param value value to add + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_env + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_env_add(hx509_context context, hx509_env *env, + const char *key, const char *value) +{ + hx509_env n; + + n = malloc(sizeof(*n)); + if (n == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + + n->type = env_string; + n->next = NULL; + n->name = strdup(key); + if (n->name == NULL) { + free(n); + return ENOMEM; + } + n->u.string = strdup(value); + if (n->u.string == NULL) { + free(n->name); + free(n); + return ENOMEM; + } + + /* add to tail */ + if (*env) { + hx509_env e = *env; + while (e->next) + e = e->next; + e->next = n; + } else + *env = n; + + return 0; +} + +/** + * Add a new key/binding pair to the hx509_env. + * + * @param context A hx509 context. + * @param env environment to add the environment variable too. + * @param key key to add + * @param list binding list to add + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_env + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_env_add_binding(hx509_context context, hx509_env *env, + const char *key, hx509_env list) +{ + hx509_env n; + + n = malloc(sizeof(*n)); + if (n == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + + n->type = env_list; + n->next = NULL; + n->name = strdup(key); + if (n->name == NULL) { + free(n); + return ENOMEM; + } + n->u.list = list; + + /* add to tail */ + if (*env) { + hx509_env e = *env; + while (e->next) + e = e->next; + e->next = n; + } else + *env = n; + + return 0; +} + + +/** + * Search the hx509_env for a length based key. + * + * @param context A hx509 context. + * @param env environment to add the environment variable too. + * @param key key to search for. + * @param len length of key. + * + * @return the value if the key is found, NULL otherwise. + * + * @ingroup hx509_env + */ + +HX509_LIB_FUNCTION const char * HX509_LIB_CALL +hx509_env_lfind(hx509_context context, hx509_env env, + const char *key, size_t len) +{ + while(env) { + if (strncmp(key, env->name ,len) == 0 + && env->name[len] == '\0' && env->type == env_string) + return env->u.string; + env = env->next; + } + return NULL; +} + +/** + * Search the hx509_env for a key. + * + * @param context A hx509 context. + * @param env environment to add the environment variable too. + * @param key key to search for. + * + * @return the value if the key is found, NULL otherwise. + * + * @ingroup hx509_env + */ + +HX509_LIB_FUNCTION const char * HX509_LIB_CALL +hx509_env_find(hx509_context context, hx509_env env, const char *key) +{ + while(env) { + if (strcmp(key, env->name) == 0 && env->type == env_string) + return env->u.string; + env = env->next; + } + return NULL; +} + +/** + * Search the hx509_env for a binding. + * + * @param context A hx509 context. + * @param env environment to add the environment variable too. + * @param key key to search for. + * + * @return the binding if the key is found, NULL if not found. + * + * @ingroup hx509_env + */ + +hx509_env +hx509_env_find_binding(hx509_context context, + hx509_env env, + const char *key) +{ + while(env) { + if (strcmp(key, env->name) == 0 && env->type == env_list) + return env->u.list; + env = env->next; + } + return NULL; +} + +static void +env_free(hx509_env b) +{ + while(b) { + hx509_env next = b->next; + + if (b->type == env_string) + free(b->u.string); + else if (b->type == env_list) + env_free(b->u.list); + + free(b->name); + free(b); + b = next; + } +} + +/** + * Free an hx509_env environment context. + * + * @param env the environment to free. + * + * @ingroup hx509_env + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_env_free(hx509_env *env) +{ + if (*env) + env_free(*env); + *env = NULL; +} diff --git a/third_party/heimdal/lib/hx509/error.c b/third_party/heimdal/lib/hx509/error.c new file mode 100644 index 0000000..aee4f79 --- /dev/null +++ b/third_party/heimdal/lib/hx509/error.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" + +/** + * @page page_error Hx509 error reporting functions + * + * See the library functions here: @ref hx509_error + */ + +struct hx509_error_data { + hx509_error next; + int code; + char *msg; +}; + +/** + * Resets the error strings the hx509 context. + * + * @param context A hx509 context. + * + * @ingroup hx509_error + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_clear_error_string(hx509_context context) +{ + if (context) { + heim_release(context->error); + context->error = NULL; + } +} + +/** + * Add an error message to the hx509 context. + * + * @param context A hx509 context. + * @param flags + * - HX509_ERROR_APPEND appends the error string to the old messages + (code is updated). + * @param code error code related to error message + * @param fmt error message format + * @param ap arguments to error message format + * + * @ingroup hx509_error + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_set_error_stringv(hx509_context context, int flags, int code, + const char *fmt, va_list ap) +{ + heim_error_t msg; + + if (context == NULL) + return; + + msg = heim_error_createv(code, fmt, ap); + if (msg) { + if (flags & HX509_ERROR_APPEND) + heim_error_append(msg, context->error); + heim_release(context->error); + } + context->error = msg; +} + +/** + * See hx509_set_error_stringv(). + * + * @param context A hx509 context. + * @param flags + * - HX509_ERROR_APPEND appends the error string to the old messages + (code is updated). + * @param code error code related to error message + * @param fmt error message format + * @param ... arguments to error message format + * + * @ingroup hx509_error + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_set_error_string(hx509_context context, int flags, int code, + const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + hx509_set_error_stringv(context, flags, code, fmt, ap); + va_end(ap); +} + +/** + * Sets ENOMEM as the error on a hx509 context. + * + * @param context A hx509 context. + * + * @ingroup hx509_error + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_enomem(hx509_context context) +{ + return heim_enomem(context->hcontext); +} + +/** + * Get an error string from context associated with error_code. + * + * @param context A hx509 context. + * @param error_code Get error message for this error code. + * + * @return error string, free with hx509_free_error_string(). + * + * @ingroup hx509_error + */ + +HX509_LIB_FUNCTION char * HX509_LIB_CALL +hx509_get_error_string(hx509_context context, int error_code) +{ + heim_string_t s = NULL; + const char *cstr = NULL; + char *str; + + if (context) { + if (context->error && + heim_error_get_code(context->error) == error_code && + (s = heim_error_copy_string(context->error))) + cstr = heim_string_get_utf8(s); + + if (cstr == NULL) + cstr = com_right(context->et_list, error_code); + + if (cstr == NULL && error_code > -1) + cstr = strerror(error_code); + } /* else this could be an error in hx509_context_init() */ + + if (cstr == NULL) + cstr = error_message(error_code); /* never returns NULL */ + + str = strdup(cstr); + heim_release(s); + return str; +} + +/** + * Free error string returned by hx509_get_error_string(). + * + * @param str error string to free. + * + * @ingroup hx509_error + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_free_error_string(char *str) +{ + free(str); +} + +/** + * Print error message and fatally exit from error code + * + * @param context A hx509 context. + * @param exit_code exit() code from process. + * @param error_code Error code for the reason to exit. + * @param fmt format string with the exit message. + * @param ... argument to format string. + * + * @ingroup hx509_error + */ + +HX509_LIB_NORETURN_FUNCTION + __attribute__ ((__noreturn__, __format__ (__printf__, 4, 5))) +void HX509_LIB_CALL +hx509_err(hx509_context context, int exit_code, + int error_code, const char *fmt, ...) +{ + va_list ap; + const char *msg; + char *str; + int ret; + + va_start(ap, fmt); + ret = vasprintf(&str, fmt, ap); + va_end(ap); + msg = hx509_get_error_string(context, error_code); + if (msg == NULL) + msg = "no error"; + + errx(exit_code, "%s: %s", ret != -1 ? str : "ENOMEM", msg); +} diff --git a/third_party/heimdal/lib/hx509/file.c b/third_party/heimdal/lib/hx509/file.c new file mode 100644 index 0000000..a22f625 --- /dev/null +++ b/third_party/heimdal/lib/hx509/file.c @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2005 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_map_file_os(const char *fn, heim_octet_string *os) +{ + size_t length; + void *data; + int ret; + + ret = rk_undumpdata(fn, &data, &length); + + os->data = data; + os->length = length; + + return ret; +} + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_unmap_file_os(heim_octet_string *os) +{ + rk_xfree(os->data); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_write_file(const char *fn, const void *data, size_t length) +{ + rk_dumpdata(fn, data, length); + return 0; +} + +/* + * + */ + +static void +print_pem_stamp(FILE *f, const char *type, const char *str) +{ + fprintf(f, "-----%s %s-----\n", type, str); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_pem_write(hx509_context context, const char *type, + hx509_pem_header *headers, FILE *f, + const void *data, size_t size) +{ + const char *p = data; + size_t length; + char *line; + +#define ENCODE_LINE_LENGTH 54 + + print_pem_stamp(f, "BEGIN", type); + + while (headers) { + fprintf(f, "%s: %s\n%s", + headers->header, headers->value, + headers->next ? "" : "\n"); + headers = headers->next; + } + + while (size > 0) { + ssize_t l; + + length = size; + if (length > ENCODE_LINE_LENGTH) + length = ENCODE_LINE_LENGTH; + + l = rk_base64_encode(p, length, &line); + if (l < 0) { + hx509_set_error_string(context, 0, ENOMEM, + "malloc - out of memory"); + return ENOMEM; + } + size -= length; + fprintf(f, "%s\n", line); + p += length; + free(line); + } + + print_pem_stamp(f, "END", type); + + return 0; +} + +/* + * + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_pem_add_header(hx509_pem_header **headers, + const char *header, const char *value) +{ + hx509_pem_header *h; + + h = calloc(1, sizeof(*h)); + if (h == NULL) + return ENOMEM; + h->header = strdup(header); + if (h->header == NULL) { + free(h); + return ENOMEM; + } + h->value = strdup(value); + if (h->value == NULL) { + free(h->header); + free(h); + return ENOMEM; + } + + h->next = *headers; + *headers = h; + + return 0; +} + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_pem_free_header(hx509_pem_header *headers) +{ + hx509_pem_header *h; + while (headers) { + h = headers; + headers = headers->next; + free(h->header); + free(h->value); + free(h); + } +} + +/* + * + */ + +HX509_LIB_FUNCTION const char * HX509_LIB_CALL +hx509_pem_find_header(const hx509_pem_header *h, const char *header) +{ + while(h) { + if (strcmp(header, h->header) == 0) + return h->value; + h = h->next; + } + return NULL; +} + + +/* + * + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_pem_read(hx509_context context, + FILE *f, + hx509_pem_read_func func, + void *ctx) +{ + hx509_pem_header *headers = NULL; + char *type = NULL; + void *data = NULL; + size_t len = 0; + char buf[1024]; + int ret = HX509_PARSING_KEY_FAILED; + + enum { BEFORE, SEARCHHEADER, INHEADER, INDATA, DONE } where; + + where = BEFORE; + + while (fgets(buf, sizeof(buf), f) != NULL) { + char *p; + int i; + + i = strcspn(buf, "\n"); + if (buf[i] == '\n') { + buf[i] = '\0'; + if (i > 0) + i--; + } + if (buf[i] == '\r') { + buf[i] = '\0'; + if (i > 0) + i--; + } + + switch (where) { + case BEFORE: + if (strncmp("-----BEGIN ", buf, 11) == 0) { + type = strdup(buf + 11); + if (type == NULL) + break; + p = strchr(type, '-'); + if (p) + *p = '\0'; + where = SEARCHHEADER; + } + break; + case SEARCHHEADER: + p = strchr(buf, ':'); + if (p == NULL) { + where = INDATA; + goto indata; + } + fallthrough; + case INHEADER: + if (buf[0] == '\0') { + where = INDATA; + break; + } + p = strchr(buf, ':'); + if (p) { + *p++ = '\0'; + while (isspace((int)*p)) + p++; + ret = hx509_pem_add_header(&headers, buf, p); + if (ret) + abort(); + } + break; + case INDATA: + indata: + + if (strncmp("-----END ", buf, 9) == 0) { + where = DONE; + break; + } + + p = emalloc(i); + i = rk_base64_decode(buf, p); + if (i < 0) { + free(p); + goto out; + } + + data = erealloc(data, len + i); + memcpy(((char *)data) + len, p, i); + free(p); + len += i; + break; + case DONE: + abort(); + } + + if (where == DONE) { + ret = (*func)(context, type, headers, data, len, ctx); + out: + free(data); + data = NULL; + len = 0; + free(type); + type = NULL; + where = BEFORE; + hx509_pem_free_header(headers); + headers = NULL; + if (ret) + break; + } + } + + if (where != BEFORE) { + hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, + "File ends before end of PEM end tag"); + ret = HX509_PARSING_KEY_FAILED; + } + if (data) + free(data); + if (type) + free(type); + if (headers) + hx509_pem_free_header(headers); + + return ret; +} + +/* + * On modern systems there's no such thing as scrubbing a file. Not this way + * anyways. However, for now we'll cargo-cult this along just as in lib/krb5. + */ +static int +scrub_file(int fd, ssize_t sz) +{ + char buf[128]; + + memset(buf, 0, sizeof(buf)); + while (sz > 0) { + ssize_t tmp; + size_t wr = sizeof(buf) > sz ? (size_t)sz : sizeof(buf); + + tmp = write(fd, buf, wr); + if (tmp == -1) + return errno; + sz -= tmp; + } +#ifdef _MSC_VER + return _commit(fd); +#else + return fsync(fd); +#endif +} + +int +_hx509_erase_file(hx509_context context, const char *fn) +{ + struct stat sb1, sb2; + int ret; + int fd; + + if (fn == NULL) + return 0; + + /* This is based on _krb5_erase_file(), minus file locking */ + ret = lstat(fn, &sb1); + if (ret == -1 && errno == ENOENT) + return 0; + if (ret == -1) { + hx509_set_error_string(context, 0, errno, "hx509_certs_destroy: " + "stat of \"%s\": %s", fn, strerror(errno)); + return errno; + } + + fd = open(fn, O_RDWR | O_BINARY | O_CLOEXEC | O_NOFOLLOW); + if (fd < 0) + return errno == ENOENT ? 0 : errno; + rk_cloexec(fd); + + if (unlink(fn) < 0) { + ret = errno; + (void) close(fd); + hx509_set_error_string(context, 0, ret, "hx509_certs_destroy: " + "unlinking \"%s\": %s", fn, strerror(ret)); + return ret; + } + + /* check TOCTOU, symlinks */ + ret = fstat(fd, &sb2); + if (ret < 0) { + ret = errno; + hx509_set_error_string(context, 0, ret, "hx509_certs_destroy: " + "fstat of %d, \"%s\": %s", fd, fn, + strerror(ret)); + (void) close(fd); + return ret; + } + if (sb1.st_dev != sb2.st_dev || sb1.st_ino != sb2.st_ino) { + (void) close(fd); + return EPERM; + } + + /* there are still hard links to this file */ + if (sb2.st_nlink != 0) { + close(fd); + return 0; + } + + ret = scrub_file(fd, sb2.st_size); + (void) close(fd); + return ret; +} diff --git a/third_party/heimdal/lib/hx509/hx509.h b/third_party/heimdal/lib/hx509/hx509.h new file mode 100644 index 0000000..75d6473 --- /dev/null +++ b/third_party/heimdal/lib/hx509/hx509.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id$ */ + +#ifndef HEIMDAL_HX509_H +#define HEIMDAL_HX509_H 1 + +#include <rfc2459_asn1.h> +#include <rfc4108_asn1.h> +#include <stdarg.h> +#include <stdio.h> +#include <heimbase.h> + +typedef struct hx509_cert_attribute_data *hx509_cert_attribute; +typedef struct hx509_cert_data *hx509_cert; +typedef struct hx509_certs_data *hx509_certs; +typedef struct hx509_context_data *hx509_context; +typedef struct hx509_crypto_data *hx509_crypto; +typedef struct hx509_lock_data *hx509_lock; +typedef struct hx509_name_data *hx509_name; +typedef struct hx509_private_key *hx509_private_key; +typedef struct hx509_private_key_ops hx509_private_key_ops; +typedef struct hx509_validate_ctx_data *hx509_validate_ctx; +typedef struct hx509_verify_ctx_data *hx509_verify_ctx; +typedef struct hx509_revoke_ctx_data *hx509_revoke_ctx; +typedef struct hx509_query_data hx509_query; +typedef void * hx509_cursor; +typedef struct hx509_request_data *hx509_request; +typedef struct hx509_error_data *hx509_error; +typedef struct hx509_peer_info *hx509_peer_info; +typedef struct hx509_ca_tbs *hx509_ca_tbs; +typedef struct hx509_env_data *hx509_env; +typedef struct hx509_crl *hx509_crl; + +typedef void (*hx509_vprint_func)(void *, const char *, va_list); + +typedef enum { + HX509_SAN_TYPE_UNSUPPORTED = 0, + /* The following correspond to the enum GeneralName_enum values: */ + HX509_SAN_TYPE_EMAIL = 2, + HX509_SAN_TYPE_DNSNAME = 3, + HX509_SAN_TYPE_DN = 4, + HX509_SAN_TYPE_REGISTERED_ID = 7, + /* + * Missing support for: + * - URI SANs + * - IP address SANs + * - various otherName SANs we know about (e.g., DNSSRV) + * + * The following are otherName SAN types, and assigned manually here: + */ + HX509_SAN_TYPE_XMPP = 32, + HX509_SAN_TYPE_PKINIT = 33, + HX509_SAN_TYPE_MS_UPN = 34, + HX509_SAN_TYPE_DNSSRV = 35, /* SRVName [RFC4985] */ + HX509_SAN_TYPE_PERMANENT_ID = 36, /* PermanentIdentifier [RFC4043] */ + HX509_SAN_TYPE_HW_MODULE = 37, /* HardwareModuleName [RFC4108] */ +} hx509_san_type; + +enum { + HX509_VHN_F_ALLOW_NO_MATCH = 1 +}; + +enum { + HX509_VALIDATE_F_VALIDATE = 1, + HX509_VALIDATE_F_VERBOSE = 2 +}; + +enum { + HX509_CRYPTO_PADDING_PKCS7 = 0, + HX509_CRYPTO_PADDING_NONE = 1 +}; + +enum { + HX509_KEY_FORMAT_GUESS = 0, + HX509_KEY_FORMAT_DER = 1, + HX509_KEY_FORMAT_WIN_BACKUPKEY = 2, + HX509_KEY_FORMAT_PKCS8 = 3, +}; +typedef uint32_t hx509_key_format_t; + +struct hx509_cert_attribute_data { + heim_oid oid; + heim_octet_string data; +}; + +typedef enum { + HX509_PROMPT_TYPE_PASSWORD = 0x1, /* password, hidden */ + HX509_PROMPT_TYPE_QUESTION = 0x2, /* question, not hidden */ + HX509_PROMPT_TYPE_INFO = 0x4 /* infomation, reply doesn't matter */ +} hx509_prompt_type; + +typedef struct hx509_prompt { + const char *prompt; + hx509_prompt_type type; + heim_octet_string reply; +} hx509_prompt; + +typedef int (*hx509_prompter_fct)(void *, const hx509_prompt *); + +typedef struct hx509_octet_string_list { + size_t len; + heim_octet_string *val; +} hx509_octet_string_list; + +typedef struct hx509_pem_header { + struct hx509_pem_header *next; + char *header; + char *value; +} hx509_pem_header; + +typedef int +(*hx509_pem_read_func)(hx509_context, const char *, const hx509_pem_header *, + const void *, size_t, void *ctx); + +/* + * Options passed to hx509_query_match_option. + */ +typedef enum { + HX509_QUERY_OPTION_PRIVATE_KEY = 1, + HX509_QUERY_OPTION_KU_ENCIPHERMENT = 2, + HX509_QUERY_OPTION_KU_DIGITALSIGNATURE = 3, + HX509_QUERY_OPTION_KU_KEYCERTSIGN = 4, + HX509_QUERY_OPTION_END = 0xffff +} hx509_query_option; + +/* flags to hx509_certs_init */ +#define HX509_CERTS_CREATE 0x01 +#define HX509_CERTS_UNPROTECT_ALL 0x02 +#define HX509_CERTS_NO_PRIVATE_KEYS 0x04 + +/* flags to hx509_certs_store */ +#define HX509_CERTS_STORE_NO_PRIVATE_KEYS 0x04 + + +/* flags to hx509_set_error_string */ +#define HX509_ERROR_APPEND 0x01 + +/* flags to hx509_cms_unenvelope */ +#define HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT 0x01 +#define HX509_CMS_UE_ALLOW_WEAK 0x02 + +/* flags to hx509_cms_envelope_1 */ +#define HX509_CMS_EV_NO_KU_CHECK 0x01 +#define HX509_CMS_EV_ALLOW_WEAK 0x02 +#define HX509_CMS_EV_ID_NAME 0x04 + +/* flags to hx509_cms_verify_signed */ +#define HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH 0x01 +#define HX509_CMS_VS_NO_KU_CHECK 0x02 +#define HX509_CMS_VS_ALLOW_ZERO_SIGNER 0x04 +#define HX509_CMS_VS_NO_VALIDATE 0x08 + +/* flags from hx509_cms_verify_signed_ext (out verify_flags) */ +#define HX509_CMS_VSE_VALIDATED 0x01 + +/* selectors passed to hx509_crypto_select and hx509_crypto_available */ +#define HX509_SELECT_ALL 0 +#define HX509_SELECT_DIGEST 1 +#define HX509_SELECT_PUBLIC_SIG 2 +#define HX509_SELECT_PUBLIC_ENC 3 +#define HX509_SELECT_SECRET_ENC 4 + +/* flags to hx509_ca_tbs_set_template */ +#define HX509_CA_TEMPLATE_SUBJECT 1 +#define HX509_CA_TEMPLATE_SERIAL 2 +#define HX509_CA_TEMPLATE_NOTBEFORE 4 +#define HX509_CA_TEMPLATE_NOTAFTER 8 +#define HX509_CA_TEMPLATE_SPKI 16 +#define HX509_CA_TEMPLATE_KU 32 +#define HX509_CA_TEMPLATE_EKU 64 +#define HX509_CA_TEMPLATE_PKINIT_MAX_LIFE 128 + +/* flags hx509_cms_create_signed* */ +#define HX509_CMS_SIGNATURE_DETACHED 0x01 +#define HX509_CMS_SIGNATURE_ID_NAME 0x02 +#define HX509_CMS_SIGNATURE_NO_SIGNER 0x04 +#define HX509_CMS_SIGNATURE_LEAF_ONLY 0x08 +#define HX509_CMS_SIGNATURE_NO_CERTS 0x10 + +/* hx509_verify_hostname nametype */ +typedef enum { + HX509_HN_HOSTNAME = 0, + HX509_HN_DNSSRV +} hx509_hostname_type; + +#include <hx509-protos.h> +#include <hx509_err.h> + +#endif /* HEIMDAL_HX509_H */ diff --git a/third_party/heimdal/lib/hx509/hx509_err.et b/third_party/heimdal/lib/hx509/hx509_err.et new file mode 100644 index 0000000..db81f5d --- /dev/null +++ b/third_party/heimdal/lib/hx509/hx509_err.et @@ -0,0 +1,110 @@ +# +# Error messages for the hx509 library +# +# This might look like a com_err file, but is not +# +id "$Id$" + +error_table hx +prefix HX509 + +# path validation and construction related errors +error_code BAD_TIMEFORMAT, "ASN.1 failed call to system time library" +error_code EXTENSION_NOT_FOUND, "Extension not found" +error_code NO_PATH, "Certification path not found" +error_code PARENT_NOT_CA, "Parent certificate is not a CA" +error_code CA_PATH_TOO_DEEP, "CA path too deep" +error_code SIG_ALG_NO_SUPPORTED, "Signature algorithm not supported" +error_code SIG_ALG_DONT_MATCH_KEY_ALG, "Signature algorithm doesn't match certificate key" +error_code CERT_USED_BEFORE_TIME, "Certificate used before it became valid" +error_code CERT_USED_AFTER_TIME, "Certificate used after it became invalid" +error_code PRIVATE_KEY_MISSING, "Private key required for the operation is missing" +error_code ALG_NOT_SUPP, "Algorithm not supported" +error_code ISSUER_NOT_FOUND, "Issuer couldn't be found" +error_code VERIFY_CONSTRAINTS, "Error verifying constraints" +error_code RANGE, "Number too large" +error_code NAME_CONSTRAINT_ERROR, "Error while verifying name constraints" +error_code PATH_TOO_LONG, "Path is too long, failed to find valid anchor" +error_code KU_CERT_MISSING, "Required keyusage for this certificate is missing" +error_code CERT_NOT_FOUND, "Certificate not found" +error_code UNKNOWN_LOCK_COMMAND, "Unknown lock command" +error_code PARENT_IS_CA, "Parent certificate is a CA" +error_code EXTRA_DATA_AFTER_STRUCTURE, "Extra data was found after the structure" +error_code PROXY_CERT_INVALID, "Proxy certificate is invalid" +error_code PROXY_CERT_NAME_WRONG, "Proxy certificate name is wrong" +error_code NAME_MALFORMED, "Name is malformed" +error_code CERTIFICATE_MALFORMED, "Certificate is malformed" +error_code CERTIFICATE_MISSING_EKU, "Certificate is missing a required EKU" +error_code PROXY_CERTIFICATE_NOT_CANONICALIZED, "Proxy certificate not canonicalized" +error_code NO_ITEM, "No such item / iteration end" + +# cms related errors +index 32 +prefix HX509_CMS +error_code FAILED_CREATE_SIGATURE, "Failed to create signature" +error_code MISSING_SIGNER_DATA, "Missing signer data" +error_code SIGNER_NOT_FOUND, "Couldn't find signers certificate" +error_code NO_DATA_AVAILABLE, "No data to perform the operation on" +error_code INVALID_DATA, "Data in the message is invalid" +error_code PADDING_ERROR, "Padding in the message invalid" +error_code NO_RECIPIENT_CERTIFICATE, "Couldn't find recipient certificate" +error_code DATA_OID_MISMATCH, "Mismatch bewteen signed type and unsigned type" + +# crypto related errors +index 64 +prefix HX509_CRYPTO +error_code INTERNAL_ERROR, "Internal error in the crypto engine" +error_code EXTERNAL_ERROR, "External error in the crypto engine" +error_code SIGNATURE_MISSING, "Signature missing for data" +error_code BAD_SIGNATURE, "Signature is not valid" +error_code SIG_NO_CONF, "Sigature doesn't provide confidentiality" +error_code SIG_INVALID_FORMAT, "Invalid format on signature" +error_code OID_MISMATCH, "Mismatch between oids" +error_code NO_PROMPTER, "No prompter function defined" +error_code SIGNATURE_WITHOUT_SIGNER, "Signature requires signer, but none available" +error_code RSA_PUBLIC_ENCRYPT, "RSA public encyption failed" +error_code RSA_PRIVATE_ENCRYPT, "RSA private encyption failed" +error_code RSA_PUBLIC_DECRYPT, "RSA public decryption failed" +error_code RSA_PRIVATE_DECRYPT, "RSA private decryption failed" +error_code ALGORITHM_BEST_BEFORE, "Algorithm has passed its best before date" +error_code KEY_FORMAT_UNSUPPORTED, "Key format is unsupported" + +# revoke related errors +index 96 +prefix HX509 +error_code CRL_USED_BEFORE_TIME, "CRL used before it became valid" +error_code CRL_USED_AFTER_TIME, "CRL used after it became invalid" +error_code CRL_INVALID_FORMAT, "CRL have invalid format" +error_code CERT_REVOKED, "Certificate is revoked" +error_code REVOKE_STATUS_MISSING, "No revoke status found for certificates" +error_code CRL_UNKNOWN_EXTENSION, "Unknown extension" +error_code REVOKE_WRONG_DATA, "Got wrong CRL/OCSP data from server" +error_code REVOKE_NOT_SAME_PARENT, "Doesn't have same parent as other certificates" +error_code CERT_NOT_IN_OCSP, "Certificates not in OCSP reply" + +# misc error +index 108 +error_code LOCAL_ATTRIBUTE_MISSING, "No local key attribute" +error_code PARSING_KEY_FAILED, "Failed to parse key" +error_code UNSUPPORTED_OPERATION, "Unsupported operation" +error_code UNIMPLEMENTED_OPERATION, "Unimplemented operation" +error_code PARSING_NAME_FAILED, "Failed to parse name" + +# keystore related error +index 128 +prefix HX509_PKCS11 +error_code NO_SLOT, "No smartcard reader/device found" +error_code NO_TOKEN, "No smartcard in reader" +error_code NO_MECH, "No supported mech(s)" +error_code TOKEN_CONFUSED, "Token or slot failed in inconsistent way" +error_code OPEN_SESSION, "Failed to open session to slot" +error_code LOGIN, "Failed to login to slot" +error_code LOAD, "Failed to load PKCS module" + +# pkinit related errors +error_code PIN_INCORRECT, "Incorrect User PIN" +error_code PIN_LOCKED, "User PIN locked" +error_code PIN_NOT_INITIALIZED, "User PIN not initialized" +error_code PIN_EXPIRED, "User PIN expired" + +end diff --git a/third_party/heimdal/lib/hx509/hx_locl.h b/third_party/heimdal/lib/hx509/hx_locl.h new file mode 100644 index 0000000..d653f7d --- /dev/null +++ b/third_party/heimdal/lib/hx509/hx_locl.h @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2004 - 2016 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id$ */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <errno.h> +#ifdef HAVE_STRINGS_H +#include <strings.h> +#endif +#include <assert.h> +#include <stdarg.h> +#include <err.h> +#include <limits.h> + +#include <roken.h> + +#include <getarg.h> +#include <base64.h> +#include <hex.h> +#include <com_err.h> +#include <parse_units.h> +#include <parse_bytes.h> + +#include <krb5-types.h> + +#include <rfc2459_asn1.h> +#include <rfc4108_asn1.h> +#include <cms_asn1.h> +#include <pkcs8_asn1.h> +#include <pkcs9_asn1.h> +#include <pkcs12_asn1.h> +#include <ocsp_asn1.h> +#include <pkcs10_asn1.h> +#include <asn1_err.h> +#include <pkinit_asn1.h> + +#include <der.h> + +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +/* + * We use OpenSSL for EC, but to do this we need to disable cross-references + * between OpenSSL and hcrypto bn.h and such. Source files that use OpenSSL EC + * must define HEIM_NO_CRYPTO_HDRS before including this file. + */ + +#define HC_DEPRECATED_CRYPTO +#ifndef HEIM_NO_CRYPTO_HDRS +#include "crypto-headers.h" +#endif + +struct hx509_keyset_ops; +struct hx509_collector; +struct hx509_generate_private_context; +typedef struct hx509_path hx509_path; + +#include <heimbase.h> + +#include <hx509.h> + +typedef void (*_hx509_cert_release_func)(struct hx509_cert_data *, void *); + + +#include "sel.h" + +#include <hx509-private.h> +#include <hx509_err.h> + +struct hx509_peer_info { + hx509_cert cert; + AlgorithmIdentifier *val; + size_t len; +}; + +#define HX509_CERTS_FIND_SERIALNUMBER 1 +#define HX509_CERTS_FIND_ISSUER 2 +#define HX509_CERTS_FIND_SUBJECT 4 +#define HX509_CERTS_FIND_ISSUER_KEY_ID 8 +#define HX509_CERTS_FIND_SUBJECT_KEY_ID 16 + +struct hx509_name_data { + Name der_name; +}; + +struct hx509_path { + size_t len; + hx509_cert *val; +}; + +struct hx509_query_data { + int match; +#define HX509_QUERY_FIND_ISSUER_CERT 0x000001 +#define HX509_QUERY_MATCH_SERIALNUMBER 0x000002 +#define HX509_QUERY_MATCH_ISSUER_NAME 0x000004 +#define HX509_QUERY_MATCH_SUBJECT_NAME 0x000008 +#define HX509_QUERY_MATCH_SUBJECT_KEY_ID 0x000010 +#define HX509_QUERY_MATCH_ISSUER_ID 0x000020 +#define HX509_QUERY_PRIVATE_KEY 0x000040 +#define HX509_QUERY_KU_ENCIPHERMENT 0x000080 +#define HX509_QUERY_KU_DIGITALSIGNATURE 0x000100 +#define HX509_QUERY_KU_KEYCERTSIGN 0x000200 +#define HX509_QUERY_KU_CRLSIGN 0x000400 +#define HX509_QUERY_KU_NONREPUDIATION 0x000800 +#define HX509_QUERY_KU_KEYAGREEMENT 0x001000 +#define HX509_QUERY_KU_DATAENCIPHERMENT 0x002000 +#define HX509_QUERY_ANCHOR 0x004000 +#define HX509_QUERY_MATCH_CERTIFICATE 0x008000 +#define HX509_QUERY_MATCH_LOCAL_KEY_ID 0x010000 +#define HX509_QUERY_NO_MATCH_PATH 0x020000 +#define HX509_QUERY_MATCH_FRIENDLY_NAME 0x040000 +#define HX509_QUERY_MATCH_FUNCTION 0x080000 +#define HX509_QUERY_MATCH_KEY_HASH_SHA1 0x100000 +#define HX509_QUERY_MATCH_TIME 0x200000 +#define HX509_QUERY_MATCH_EKU 0x400000 +#define HX509_QUERY_MATCH_EXPR 0x800000 +#define HX509_QUERY_MASK 0xffffff + Certificate *subject; + Certificate *certificate; + heim_integer *serial; + heim_octet_string *subject_id; + heim_octet_string *local_key_id; + Name *issuer_name; + Name *subject_name; + hx509_path *path; + char *friendlyname; + int (*cmp_func)(hx509_context, hx509_cert, void *); + void *cmp_func_ctx; + heim_octet_string *keyhash_sha1; + time_t timenow; + heim_oid *eku; + struct hx_expr *expr; +}; + +struct hx509_keyset_ops { + const char *name; + int flags; + int (*init)(hx509_context, hx509_certs, void **, + int, const char *, hx509_lock); + int (*store)(hx509_context, hx509_certs, void *, int, hx509_lock); + int (*free)(hx509_certs, void *); + int (*add)(hx509_context, hx509_certs, void *, hx509_cert); + int (*query)(hx509_context, hx509_certs, void *, + const hx509_query *, hx509_cert *); + int (*iter_start)(hx509_context, hx509_certs, void *, void **); + int (*iter)(hx509_context, hx509_certs, void *, void *, hx509_cert *); + int (*iter_end)(hx509_context, hx509_certs, void *, void *); + int (*printinfo)(hx509_context, hx509_certs, + void *, int (*)(void *, const char *), void *); + int (*getkeys)(hx509_context, hx509_certs, void *, hx509_private_key **); + int (*addkey)(hx509_context, hx509_certs, void *, hx509_private_key); + int (*destroy)(hx509_context, hx509_certs, void *); +}; + +struct _hx509_password { + size_t len; + char **val; +}; + +extern hx509_lock _hx509_empty_lock; + +struct hx509_context_data { + struct hx509_keyset_ops **ks_ops; + int ks_num_ops; + int flags; +#define HX509_CTX_VERIFY_MISSING_OK 1 + int ocsp_time_diff; +#define HX509_DEFAULT_OCSP_TIME_DIFF (5*60) + heim_error_t error; + struct et_list *et_list; + char *querystat; + hx509_certs default_trust_anchors; + heim_context hcontext; + heim_config_section *cf; +}; + +/* _hx509_calculate_path flag field */ +#define HX509_CALCULATE_PATH_NO_ANCHOR 1 + +/* environment */ +struct hx509_env_data { + enum { env_string, env_list } type; + char *name; + struct hx509_env_data *next; + union { + char *string; + struct hx509_env_data *list; + } u; +}; + + +extern const AlgorithmIdentifier * _hx509_crypto_default_sig_alg; +extern const AlgorithmIdentifier * _hx509_crypto_default_digest_alg; +extern const AlgorithmIdentifier * _hx509_crypto_default_secret_alg; + +/* + * Private bits from crypto.c, so crypto-ec.c can also see them. + * + * This is part of the use-OpenSSL-for-EC hack. + */ + +struct hx509_crypto; + +struct signature_alg; + +struct hx509_generate_private_context { + const heim_oid *key_oid; + int isCA; + unsigned long num_bits; +}; + +struct hx509_private_key_ops { + const char *pemtype; + const heim_oid *key_oid; + int (*available)(const hx509_private_key, + const AlgorithmIdentifier *); + int (*get_spki)(hx509_context, + const hx509_private_key, + SubjectPublicKeyInfo *); + int (*export)(hx509_context context, + const hx509_private_key, + hx509_key_format_t, + heim_octet_string *); + int (*import)(hx509_context, const AlgorithmIdentifier *, + const void *, size_t, hx509_key_format_t, + hx509_private_key); + int (*generate_private_key)(hx509_context, + struct hx509_generate_private_context *, + hx509_private_key); + BIGNUM *(*get_internal)(hx509_context, hx509_private_key, const char *); +}; + +struct hx509_private_key { + unsigned int ref; + const struct signature_alg *md; + const heim_oid *signature_alg; + union { + RSA *rsa; + void *keydata; + void *ecdsa; /* EC_KEY */ + } private_key; + hx509_private_key_ops *ops; +}; + +/* + * + */ + +struct signature_alg { + const char *name; + const heim_oid *sig_oid; + const AlgorithmIdentifier *sig_alg; + const heim_oid *key_oid; + const AlgorithmIdentifier *digest_alg; + int flags; +#define PROVIDE_CONF 0x1 +#define REQUIRE_SIGNER 0x2 +#define SELF_SIGNED_OK 0x4 +#define WEAK_SIG_ALG 0x8 + +#define SIG_DIGEST 0x100 +#define SIG_PUBLIC_SIG 0x200 +#define SIG_SECRET 0x400 + +#define RA_RSA_USES_DIGEST_INFO 0x1000000 + + time_t best_before; /* refuse signature made after best before date */ + const EVP_MD *(*evp_md)(void); + int (*verify_signature)(hx509_context context, + const struct signature_alg *, + const Certificate *, + const AlgorithmIdentifier *, + const heim_octet_string *, + const heim_octet_string *); + int (*create_signature)(hx509_context, + const struct signature_alg *, + const hx509_private_key, + const AlgorithmIdentifier *, + const heim_octet_string *, + AlgorithmIdentifier *, + heim_octet_string *); + int digest_size; +}; + +/* + * Configurable options + */ + +#ifdef __APPLE__ +#define HX509_DEFAULT_ANCHORS "KEYCHAIN:system-anchors" +#endif diff --git a/third_party/heimdal/lib/hx509/hxtool-commands.in b/third_party/heimdal/lib/hx509/hxtool-commands.in new file mode 100644 index 0000000..279095d --- /dev/null +++ b/third_party/heimdal/lib/hx509/hxtool-commands.in @@ -0,0 +1,1057 @@ +/* + * Copyright (c) 2005 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* $Id$ */ + +command = { + name = "list-oids" + help = "List known OIDs" + function = "hxtool_list_oids" + min_args="0" + max_args="0" +} +command = { + name = "cms-create-sd" + name = "cms-sign" + option = { + long = "certificate" + short = "c" + type = "strings" + argument = "certificate-store" + help = "certificate stores to pull certificates from" + } + option = { + long = "signer" + short = "s" + type = "string" + argument = "signer-friendly-name" + help = "certificate to sign with" + } + option = { + long = "anchors" + type = "strings" + argument = "certificate-store" + help = "trust anchors" + } + option = { + long = "pool" + type = "strings" + argument = "certificate-pool" + help = "certificate store to pull certificates from" + } + option = { + long = "pass" + type = "strings" + argument = "password" + help = "password, prompter, or environment" + } + option = { + long = "peer-alg" + type = "strings" + argument = "oid" + help = "oid that the peer support" + } + option = { + long = "content-type" + type = "string" + argument = "oid" + help = "content type oid" + } + option = { + long = "content-info" + type = "flag" + help = "wrapped out-data in a ContentInfo" + } + option = { + long = "pem" + type = "flag" + help = "wrap out-data in PEM armor" + } + option = { + long = "detached-signature" + type = "flag" + help = "create a detached signature" + } + option = { + long = "signer" + type = "-flag" + help = "do not sign" + } + option = { + long = "id-by-name" + type = "flag" + help = "use subject name for CMS Identifier" + } + option = { + long = "embedded-certs" + type = "-flag" + help = "don't embed certificates" + } + option = { + long = "embed-leaf-only" + type = "flag" + help = "only embed leaf certificate" + } + min_args="1" + max_args="2" + argument="in-file out-file" + help = "Wrap a file within a SignedData object" +} +command = { + name = "cms-verify-sd" + option = { + long = "anchors" + short = "D" + type = "strings" + argument = "certificate-store" + help = "trust anchors" + } + option = { + long = "certificate" + short = "c" + type = "strings" + argument = "certificate-store" + help = "certificate store to pull certificates from" + } + option = { + long = "pass" + type = "strings" + argument = "password" + help = "password, prompter, or environment" + } + option = { + long = "missing-revoke" + type = "flag" + help = "missing CRL/OCSP is ok" + } + option = { + long = "content-info" + type = "flag" + help = "unwrap in-data that's in a ContentInfo" + } + option = { + long = "pem" + type = "flag" + help = "unwrap in-data from PEM armor" + } + option = { + long = "signer-allowed" + type = "-flag" + help = "allow no signer" + } + option = { + long = "allow-wrong-oid" + type = "flag" + help = "allow wrong oid flag" + } + option = { + long = "signed-content" + type = "string" + help = "file containing content" + } + option = { + long = "oid-sym" + type = "flag" + help = "show symbolic name for OID" + } + min_args="1" + max_args="2" + argument="in-file [out-file]" + help = "Verify a file within a SignedData object" +} +command = { + name = "cms-unenvelope" + option = { + long = "certificate" + short = "c" + type = "strings" + argument = "certificate-store" + help = "certificate used to decrypt the data" + } + option = { + long = "pass" + type = "strings" + argument = "password" + help = "password, prompter, or environment" + } + option = { + long = "content-info" + type = "flag" + help = "wrapped out-data in a ContentInfo" + } + option = { + long = "allow-weak-crypto" + type = "flag" + help = "allow weak crypto" + } + min_args="2" + argument="in-file out-file" + help = "Unenvelope a file containing a EnvelopedData object" +} +command = { + name = "cms-envelope" + function = "cms_create_enveloped" + option = { + long = "certificate" + short = "c" + type = "strings" + argument = "certificate-store" + help = "certificates used to receive the data" + } + option = { + long = "pass" + type = "strings" + argument = "password" + help = "password, prompter, or environment" + } + option = { + long = "encryption-type" + type = "string" + argument = "enctype" + help = "enctype" + } + option = { + long = "content-type" + type = "string" + argument = "oid" + help = "content type oid" + } + option = { + long = "content-info" + type = "flag" + help = "wrapped out-data in a ContentInfo" + } + option = { + long = "allow-weak-crypto" + type = "flag" + help = "allow weak crypto" + } + min_args="2" + argument="in-file out-file" + help = "Envelope a file containing a EnvelopedData object" +} +command = { + name = "verify" + function = "pcert_verify" + option = { + long = "pass" + type = "strings" + argument = "password" + help = "password, prompter, or environment" + } + option = { + long = "allow-proxy-certificate" + type = "flag" + help = "allow proxy certificates" + } + option = { + long = "missing-revoke" + type = "flag" + help = "missing CRL/OCSP is ok" + } + option = { + long = "time" + type = "string" + help = "time when to validate the chain" + } + option = { + long = "verbose" + short = "v" + type = "flag" + help = "verbose logging" + } + option = { + long = "max-depth" + type = "integer" + help = "maximum search length of certificate trust anchor" + } + option = { + long = "hostname" + type = "string" + help = "match hostname to certificate" + } + argument = "cert:foo chain:cert1 chain:cert2 anchor:anchor1 anchor:anchor2" + help = "Verify certificate chain" +} +command = { + name = "print" + function = "pcert_print" + option = { + long = "pass" + type = "strings" + argument = "password" + help = "password, prompter, or environment" + } + option = { + long = "content" + type = "flag" + help = "print the content of the certificates" + } + option = { + long = "raw-json" + type = "flag" + help = "print the DER content of the certificates as JSON" + } + option = { + long = "never-fail" + type = "flag" + help = "never fail with an error code" + } + option = { + long = "info" + type = "flag" + help = "print the information about the certificate store" + } + min_args="1" + argument="certificate ..." + help = "Print certificates" +} +command = { + name = "validate" + function = "pcert_validate" + option = { + long = "pass" + type = "strings" + argument = "password" + help = "password, prompter, or environment" + } + min_args="1" + argument="certificate ..." + help = "Validate content of certificates" +} +command = { + name = "certificate-copy" + name = "cc" + option = { + long = "in-pass" + type = "strings" + argument = "password" + help = "password, prompter, or environment" + } + option = { + long = "out-pass" + type = "string" + argument = "password" + help = "password, prompter, or environment" + } + min_args="2" + argument="in-certificates-1 ... out-certificate" + help = "Copy in certificates stores into out certificate store" +} +command = { + name = "ocsp-fetch" + option = { + long = "pass" + type = "strings" + argument = "password" + help = "password, prompter, or environment" + } + option = { + long = "sign" + type = "string" + argument = "certificate" + help = "certificate use to sign the request" + } + option = { + long = "url-path" + type = "string" + argument = "url" + help = "part after host in url to put in the request" + } + option = { + long = "nonce" + type = "-flag" + default = "1" + help = "don't include nonce in request" + } + option = { + long = "pool" + type = "strings" + argument = "certificate-store" + help = "pool to find parent certificate in" + } + min_args="2" + argument="outfile certs ..." + help = "Fetch OCSP responses for the following certs" +} +command = { + option = { + long = "ocsp-file" + type = "string" + help = "OCSP file" + } + name = "ocsp-verify" + min_args="1" + argument="certificates ..." + help = "Check that certificates are in OCSP file and valid" +} +command = { + name = "ocsp-print" + option = { + long = "verbose" + type = "flag" + help = "verbose" + } + min_args="1" + argument="ocsp-response-file ..." + help = "Print the OCSP responses" +} +command = { + name = "revoke-print" + option = { + long = "verbose" + type = "flag" + help = "verbose" + } + min_args="1" + argument="ocsp/crl files" + help = "Print the OCSP/CRL files" +} +command = { + name = "generate-key" + option = { + long = "type" + type = "string" + help = "keytype" + } + option = { + long = "key-bits" + type = "integer" + help = "number of bits in the generated key"; + } + option = { + long = "verbose" + type = "flag" + help = "verbose status" + } + min_args="1" + max_args="1" + argument="output-file" + help = "Generate a private key" +} +command = { + name = "request-create" + option = { + long = "subject" + type = "string" + help = "Subject DN" + } + option = { + long = "eku" + type = "strings" + argument = "oid-string" + help = "Add Extended Key Usage OID" + } + option = { + long = "email" + type = "strings" + help = "Email address in SubjectAltName" + } + option = { + long = "jid" + type = "strings" + help = "XMPP (Jabber) address in SubjectAltName" + } + option = { + long = "dnsname" + type = "strings" + help = "Hostname or domainname in SubjectAltName" + } + option = { + long = "kerberos" + type = "strings" + help = "Kerberos principal name as SubjectAltName" + } + option = { + long = "ms-kerberos" + type = "strings" + help = "Kerberos principal name as SubjectAltName (Microsoft variant)" + } + option = { + long = "registered" + type = "strings" + help = "Registered object ID as SubjectAltName" + } + option = { + long = "dn" + type = "strings" + help = "Directory name as SubjectAltName" + } + option = { + long = "type" + type = "string" + help = "Type of request CRMF or PKCS10, defaults to PKCS10" + } + option = { + long = "key" + type = "string" + help = "Key-pair" + } + option = { + long = "generate-key" + type = "string" + help = "keytype" + } + option = { + long = "key-bits" + type = "integer" + help = "number of bits in the generated key"; + } + option = { + long = "verbose" + type = "flag" + help = "verbose status" + } + min_args="1" + max_args="1" + argument="output-file" + help = "Create a CRMF or PKCS10 request" +} +command = { + name = "request-print" + option = { + long = "verbose" + type = "flag" + help = "verbose printing" + } + min_args="1" + argument="requests ..." + help = "Print requests" +} +command = { + name = "query" + option = { + long = "exact" + type = "flag" + help = "exact match" + } + option = { + long = "private-key" + type = "flag" + help = "search for private key" + } + option = { + long = "friendlyname" + type = "string" + argument = "name" + help = "match on friendly name" + } + option = { + long = "eku" + type = "string" + argument = "oid-string" + help = "match on EKU" + } + option = { + long = "expr" + type = "string" + argument = "expression" + help = "match on expression" + } + option = { + long = "keyEncipherment" + type = "flag" + help = "match keyEncipherment certificates" + } + option = { + long = "digitalSignature" + type = "flag" + help = "match digitalSignature certificates" + } + option = { + long = "print" + type = "flag" + help = "print matches" + } + option = { + long = "pass" + type = "strings" + argument = "password" + help = "password, prompter, or environment" + } + min_args="1" + argument="certificates ..." + help = "Query the certificates for a match" +} +command = { + name = "info" +} +command = { + name = "random-data" + min_args="1" + argument="bytes" + help = "Generates random bytes and prints them to standard output" +} +command = { + option = { + long = "type" + type = "string" + help = "type of CMS algorithm" + } + option = { + long = "oid-syms" + type = "flag" + help = "show symbolic names for OIDs" + } + name = "crypto-available" + min_args="0" + help = "Print available CMS crypto types" +} +command = { + option = { + long = "type" + type = "string" + help = "type of CMS algorithm" + } + option = { + long = "certificate" + type = "string" + help = "source certificate limiting the choices" + } + option = { + long = "peer-cmstype" + type = "strings" + help = "peer limiting cmstypes" + } + option = { + long = "oid-sym" + type = "flag" + help = "show symbolic name for OID" + } + name = "crypto-select" + min_args="0" + help = "Print selected CMS type" +} +command = { + option = { + long = "decode" + short = "d" + type = "flag" + help = "decode instead of encode" + } + name = "hex" + function = "hxtool_hex" + min_args="0" + help = "Encode input to hex" +} +command = { + option = { + long = "issue-ca" + type = "flag" + help = "Issue a CA certificate" + } + option = { + long = "issue-proxy" + type = "flag" + help = "Issue a proxy certificate" + } + option = { + long = "domain-controller" + type = "flag" + help = "Issue a MS domaincontroller certificate" + } + option = { + long = "subject" + type = "string" + help = "Subject of issued certificate" + } + option = { + long = "ca-certificate" + type = "string" + help = "Issuing CA certificate" + } + option = { + long = "self-signed" + type = "flag" + help = "Issuing a self-signed certificate" + } + option = { + long = "ca-private-key" + type = "string" + help = "Private key for self-signed certificate" + } + option = { + long = "certificate" + type = "string" + help = "Issued certificate" + } + option = { + long = "type" + type = "strings" + help = "Types of certificate to issue (can be used more then once)" + } + option = { + long = "lifetime" + type = "string" + help = "Lifetime of certificate" + } + option = { + long = "signature-algorithm" + type = "string" + help = "Signature algorithm to use" + } + option = { + long = "serial-number" + type = "string" + help = "serial-number of certificate" + } + option = { + long = "path-length" + default = "-1" + type = "integer" + help = "Maximum path length (CA and proxy certificates), -1 no limit" + } + option = { + long = "eku" + type = "strings" + argument = "oid-string" + help = "Add Extended Key Usage OID" + } + option = { + long = "ku" + type = "strings" + help = "Key Usage (digitalSignature, keyEncipherment, dataEncipherment, keyAgreement, keyCertSign, cRLSign, encipherOnly, decipherOnly)" + } + option = { + long = "hostname" + type = "strings" + help = "DNS names this certificate is allowed to serve" + } + option = { + long = "dnssrv" + type = "strings" + help = "DNS SRV names this certificate is allowed to serve" + } + option = { + long = "email" + type = "strings" + help = "email addresses assigned to this certificate" + } + option = { + long = "pk-init-principal" + type = "strings" + help = "PK-INIT principal (for SAN)" + } + option = { + long = "ms-upn" + type = "string" + help = "Microsoft UPN (for SAN)" + } + option = { + long = "jid" + type = "string" + help = "XMPP jabber id (for SAN)" + } + option = { + long = "permanent-id" + type = "string" + help = "PermanentIdentifier ([oid]:[serial])" + } + option = { + long = "hardware-module-name" + type = "string" + help = "HardwareModuleName (oid:serial)" + } + option = { + long = "policy" + type = "strings" + help = "Certificate Policy OID and optional URI and/or notice (OID:URI<space>notice_text)" + } + option = { + long = "policy-mapping" + type = "strings" + help = "Certificate Policy mapping (OID:OID)" + } + option = { + long = "pkinit-max-life" + type = "string" + help = "maximum Kerberos ticket lifetime extension for PKINIT" + } + option = { + long = "req" + type = "string" + help = "certificate request" + } + option = { + long = "certificate-private-key" + type = "string" + help = "private-key" + } + option = { + long = "generate-key" + type = "string" + help = "keytype" + } + option = { + long = "key-bits" + type = "integer" + help = "number of bits in the generated key" + } + option = { + long = "crl-uri" + type = "string" + help = "URI to CRL" + } + option = { + long = "template-certificate" + type = "string" + help = "certificate" + } + option = { + long = "template-fields" + type = "string" + help = "flag" + } + name = "certificate-sign" + name = "cert-sign" + name = "issue-certificate" + name = "ca" + function = "hxtool_ca" + min_args="0" + help = "Issue a certificate" +} +command = { + name = "test-crypto" + option = { + long = "pass" + type = "strings" + argument = "password" + help = "password, prompter, or environment" + } + option = { + long = "verbose" + type = "flag" + help = "verbose printing" + } + min_args="1" + argument="certificates..." + help = "Test crypto system related to the certificates" +} +command = { + option = { + long = "type" + type = "integer" + help = "type of statistics" + } + name = "statistic-print" + min_args="0" + help = "Print statistics" +} +command = { + option = { + long = "signer" + type = "string" + help = "signer certificate" + } + option = { + long = "pass" + type = "strings" + argument = "password" + help = "password, prompter, or environment" + } + option = { + long = "crl-file" + type = "string" + help = "CRL output file" + } + option = { + long = "lifetime" + type = "string" + help = "time the crl will be valid" + } + name = "crl-sign" + min_args="0" + argument="certificates..." + help = "Create a CRL" +} +command = { + option = { + long = "verbose" + short = "v" + type = "flag" + help = "verbose" + } + option = { + long = "end-entity" + type = "flag" + help = "check the first EE certificate in the store" + } + option = { + long = "ca" + type = "flag" + help = "check the first CA certificate in the store" + } + option = { + long = "cert-num" + type = "integer" + default = "-1" + help = "check the nth certificate in the store" + } + option = { + long = "expr" + type = "string" + argument = "expression" + help = "test the first certificate matching expression" + } + option = { + long = "has-email-san" + short = "M" + type = "strings" + argument = "email-address" + help = "check that cert has email SAN" + } + option = { + long = "has-xmpp-san" + type = "strings" + short = "X" + argument = "jabber address" + help = "check that cert has XMPP SAN" + } + option = { + long = "has-ms-upn-san" + short = "U" + type = "strings" + argument = "UPN" + help = "check that cert has UPN SAN" + } + option = { + long = "has-dnsname-san" + short = "D" + type = "strings" + argument = "domainname" + help = "check that cert has domainname SAN" + } + option = { + long = "has-pkinit-san" + short = "P" + type = "strings" + argument = "Kerberos principal name" + help = "check that cert has PKINIT SAN" + } + option = { + long = "has-registeredID-san" + short = "R" + type = "strings" + argument = "OID" + help = "check that cert has registeredID SAN" + } + option = { + long = "has-eku" + short = "E" + type = "strings" + argument = "OID" + help = "check that cert has EKU" + } + option = { + long = "has-ku" + short = "K" + type = "strings" + argument = "key usage element" + help = "check that cert has key usage" + } + option = { + long = "exact" + type = "flag" + help = "check that cert has only given SANs/EKUs/KUs" + } + option = { + long = "valid-now" + short = "n" + type = "flag" + help = "check that current time is in certicate's validity period" + } + option = { + long = "valid-at" + type = "string" + argument = "datetime" + help = "check that the certificate is valid at given time" + } + option = { + long = "not-after-eq" + type = "string" + argument = "datetime" + help = "check that the certificate's notAfter is as given" + } + option = { + long = "not-after-lt" + type = "string" + argument = "datetime" + help = "check that the certificate's notAfter is before the given time" + } + option = { + long = "not-after-gt" + type = "string" + argument = "datetime" + help = "check that the certificate's notAfter is after the given time" + } + option = { + long = "not-before-eq" + type = "string" + argument = "datetime" + help = "check that the certificate's notBefore is as given" + } + option = { + long = "not-before-lt" + type = "string" + argument = "datetime" + help = "check that the certificate's notBefore is before the given time" + } + option = { + long = "not-before-gt" + type = "string" + argument = "datetime" + help = "check that the certificate's notBefore is after the given time" + } + option = { + long = "has-private-key" + type = "flag" + help = "check that the certificate has a private key" + } + option = { + long = "lacks-private-key" + type = "flag" + help = "check that the certificate does not have a private key" + } + name = "acert" + min_args = "1" + max_args = "1" + argument = "certificate-store" + help = "Assert certificate content" +} +command = { + name = "help" + name = "?" + argument = "[command]" + min_args = "0" + max_args = "1" + help = "Help! I need somebody" +} diff --git a/third_party/heimdal/lib/hx509/hxtool-version.rc b/third_party/heimdal/lib/hx509/hxtool-version.rc new file mode 100644 index 0000000..7e5197c --- /dev/null +++ b/third_party/heimdal/lib/hx509/hxtool-version.rc @@ -0,0 +1,36 @@ +/*********************************************************************** + * Copyright (c) 2010, Secure Endpoints Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + **********************************************************************/ + +#define RC_FILE_TYPE VFT_APP +#define RC_FILE_DESC_0409 "Heimdal X.509 Certificate Tool" +#define RC_FILE_ORIG_0409 "hxtool.exe" + +#include "../../windows/version.rc" diff --git a/third_party/heimdal/lib/hx509/hxtool.c b/third_party/heimdal/lib/hx509/hxtool.c new file mode 100644 index 0000000..1bcfdfa --- /dev/null +++ b/third_party/heimdal/lib/hx509/hxtool.c @@ -0,0 +1,3162 @@ +/* + * Copyright (c) 2004 - 2016 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" + +#include <hxtool-commands.h> +#include <sl.h> +#include <rtbl.h> +#include <parse_time.h> + +static hx509_context context; + +static char *stat_file_string; +static int version_flag; +static int help_flag; + +struct getargs args[] = { + { "statistic-file", 0, arg_string, &stat_file_string, NULL, NULL }, + { "version", 0, arg_flag, &version_flag, NULL, NULL }, + { "help", 0, arg_flag, &help_flag, NULL, NULL } +}; +int num_args = sizeof(args) / sizeof(args[0]); + +static void +usage(int code) +{ + arg_printusage(args, num_args, NULL, "command"); + printf("Use \"%s help\" to get more help\n", getprogname()); + exit(code); +} + +/* + * + */ + +static void +lock_strings(hx509_lock lock, getarg_strings *pass) +{ + int i; + for (i = 0; i < pass->num_strings; i++) { + int ret = hx509_lock_command_string(lock, pass->strings[i]); + if (ret) + errx(1, "hx509_lock_command_string: %s: %d", + pass->strings[i], ret); + } +} + +static char * +fix_store_name(hx509_context contextp, const char *sn, const char *def_type) +{ + const char *residue = strchr(sn, ':'); + char *s = NULL; + + if (residue) { + s = estrdup(sn); + s[residue - sn] = '\0'; + if (_hx509_ks_type(contextp, s)) { + free(s); + return estrdup(sn); + } + free(s); + s = NULL; + } + if (asprintf(&s, "%s:%s", def_type, sn) == -1 || s == NULL) + err(1, "Out of memory"); + return s; +} + +static char * +fix_csr_name(const char *cn, const char *def_type) +{ + char *s = NULL; + + if (strncmp(cn, "PKCS10:", sizeof("PKCS10:") - 1) == 0 || strchr(cn, ':')) + return estrdup(cn); + if (asprintf(&s, "%s:%s", def_type, cn) == -1 || s == NULL) + err(1, "Out of memory"); + return s; +} + +/* + * + */ + +static void +certs_strings(hx509_context contextp, const char *type, hx509_certs certs, + hx509_lock lock, const getarg_strings *s) +{ + int i, ret; + + for (i = 0; i < s->num_strings; i++) { + char *sn = fix_store_name(contextp, s->strings[i], "FILE"); + + ret = hx509_certs_append(contextp, certs, lock, sn); + if (ret) + hx509_err(contextp, 1, ret, + "hx509_certs_append: %s %s", type, sn); + free(sn); + } +} + +/* + * + */ + +static void +parse_oid(const char *str, const heim_oid *def, heim_oid *oid) +{ + int ret; + + if (str) { + const heim_oid *found = NULL; + + ret = der_find_heim_oid_by_name(str, &found); + if (ret == 0) + ret = der_copy_oid(found, oid); + else + ret = der_parse_heim_oid(str, " .", oid); + } else { + ret = der_copy_oid(def, oid); + } + if (ret) + errx(1, "parse_oid failed for: %s", str ? str : "default oid"); +} + +/* + * + */ + +static void +peer_strings(hx509_context contextp, + hx509_peer_info *peer, + const getarg_strings *s) +{ + AlgorithmIdentifier *val; + int ret, i; + + ret = hx509_peer_info_alloc(contextp, peer); + if (ret) + hx509_err(contextp, 1, ret, "hx509_peer_info_alloc"); + + val = calloc(s->num_strings, sizeof(*val)); + if (val == NULL) + err(1, "malloc"); + + for (i = 0; i < s->num_strings; i++) + parse_oid(s->strings[i], NULL, &val[i].algorithm); + + ret = hx509_peer_info_set_cms_algs(contextp, *peer, val, s->num_strings); + if (ret) + hx509_err(contextp, 1, ret, "hx509_peer_info_set_cms_algs"); + + for (i = 0; i < s->num_strings; i++) + free_AlgorithmIdentifier(&val[i]); + free(val); +} + +/* + * + */ + +struct pem_data { + heim_octet_string *os; + int detached_data; +}; + +static int +pem_reader(hx509_context contextp, const char *type, + const hx509_pem_header *headers, + const void *data , size_t length, void *ctx) +{ + struct pem_data *p = (struct pem_data *)ctx; + const char *h; + + p->os->data = malloc(length); + if (p->os->data == NULL) + return ENOMEM; + memcpy(p->os->data, data, length); + p->os->length = length; + + h = hx509_pem_find_header(headers, "Content-disposition"); + if (h && strcasecmp(h, "detached") == 0) + p->detached_data = 1; + + return 0; +} + +/* + * + */ + +int +cms_verify_sd(struct cms_verify_sd_options *opt, int argc, char **argv) +{ + hx509_verify_ctx ctx = NULL; + heim_oid type; + heim_octet_string c, co, signeddata, *sd = NULL; + hx509_certs store = NULL; + hx509_certs signers = NULL; + hx509_certs anchors = NULL; + hx509_lock lock; + int ret, flags = 0; + + size_t sz; + void *p = NULL; + + if (opt->missing_revoke_flag) + hx509_context_set_missing_revoke(context, 1); + + hx509_lock_init(context, &lock); + lock_strings(lock, &opt->pass_strings); + + ret = hx509_verify_init_ctx(context, &ctx); + if (ret) + hx509_err(context, 1, ret, "hx509_verify_init_ctx"); + + ret = hx509_certs_init(context, "MEMORY:cms-anchors", 0, NULL, &anchors); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); + ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &store); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); + + certs_strings(context, "anchors", anchors, lock, &opt->anchors_strings); + certs_strings(context, "store", store, lock, &opt->certificate_strings); + + if (opt->pem_flag) { + struct pem_data pd; + FILE *f; + + pd.os = &co; + pd.detached_data = 0; + + f = fopen(argv[0], "r"); + if (f == NULL) + err(1, "Failed to open file %s", argv[0]); + + ret = hx509_pem_read(context, f, pem_reader, &pd); + fclose(f); + if (ret) + errx(1, "PEM reader failed: %d", ret); + + if (pd.detached_data && opt->signed_content_string == NULL) { + char *r = strrchr(argv[0], '.'); + if (r && strcasecmp(r, ".pem") == 0) { + char *s = strdup(argv[0]); + if (s == NULL) + errx(1, "malloc: out of memory"); + s[r - argv[0]] = '\0'; + ret = _hx509_map_file_os(s, &signeddata); + if (ret) + errx(1, "map_file: %s: %d", s, ret); + free(s); + sd = &signeddata; + } + } + + } else { + ret = rk_undumpdata(argv[0], &p, &sz); + if (ret) + err(1, "map_file: %s: %d", argv[0], ret); + + co.data = p; + co.length = sz; + } + + if (opt->signed_content_string) { + ret = _hx509_map_file_os(opt->signed_content_string, &signeddata); + if (ret) + errx(1, "map_file: %s: %d", opt->signed_content_string, ret); + sd = &signeddata; + } + + if (opt->content_info_flag) { + heim_octet_string uwco; + heim_oid oid; + + ret = hx509_cms_unwrap_ContentInfo(&co, &oid, &uwco, NULL); + if (ret) + errx(1, "hx509_cms_unwrap_ContentInfo: %d", ret); + + if (der_heim_oid_cmp(&oid, &asn1_oid_id_pkcs7_signedData) != 0) + errx(1, "Content is not SignedData"); + der_free_oid(&oid); + + if (p == NULL) + der_free_octet_string(&co); + else { + rk_xfree(p); + p = NULL; + } + co = uwco; + } + + hx509_verify_attach_anchors(ctx, anchors); + + if (!opt->signer_allowed_flag) + flags |= HX509_CMS_VS_ALLOW_ZERO_SIGNER; + if (opt->allow_wrong_oid_flag) + flags |= HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH; + + ret = hx509_cms_verify_signed(context, ctx, flags, co.data, co.length, sd, + store, &type, &c, &signers); + if (p != co.data) + der_free_octet_string(&co); + else + rk_xfree(p); + if (ret) + hx509_err(context, 1, ret, "hx509_cms_verify_signed"); + + { + char *str; + if (opt->oid_sym_flag) + der_print_heim_oid_sym(&type, '.', &str); + else + der_print_heim_oid(&type, '.', &str); + printf("type: %s\n", str); + free(str); + der_free_oid(&type); + } + if (signers == NULL) { + printf("unsigned\n"); + } else { + printf("signers:\n"); + hx509_certs_iter_f(context, signers, hx509_ci_print_names, stdout); + } + + hx509_verify_destroy_ctx(ctx); + + hx509_certs_free(&store); + hx509_certs_free(&signers); + hx509_certs_free(&anchors); + + hx509_lock_free(lock); + + if (argc > 1) { + ret = _hx509_write_file(argv[1], c.data, c.length); + if (ret) + errx(1, "hx509_write_file: %d", ret); + } + + der_free_octet_string(&c); + + if (sd) + _hx509_unmap_file_os(sd); + + return 0; +} + +static int HX509_LIB_CALL +print_signer(hx509_context contextp, void *ctx, hx509_cert cert) +{ + hx509_pem_header **header = ctx; + char *signer_name = NULL; + hx509_name name; + int ret; + + ret = hx509_cert_get_subject(cert, &name); + if (ret) + errx(1, "hx509_cert_get_subject"); + + ret = hx509_name_to_string(name, &signer_name); + hx509_name_free(&name); + if (ret) + errx(1, "hx509_name_to_string"); + + hx509_pem_add_header(header, "Signer", signer_name); + + free(signer_name); + return 0; +} + +int +cms_create_sd(struct cms_create_sd_options *opt, int argc, char **argv) +{ + heim_oid contentType; + hx509_peer_info peer = NULL; + heim_octet_string o; + hx509_query *q; + hx509_lock lock; + hx509_certs store, pool, anchors, signer = NULL; + size_t sz; + void *p; + int ret, flags = 0; + const char *outfile = NULL; + char *infile, *freeme = NULL; + + memset(&contentType, 0, sizeof(contentType)); + + infile = argv[0]; + + if (argc < 2) { + ret = asprintf(&freeme, "%s.%s", infile, + opt->pem_flag ? "pem" : "cms-signeddata"); + if (ret == -1 || freeme == NULL) + errx(1, "out of memory"); + outfile = freeme; + } else + outfile = argv[1]; + + hx509_lock_init(context, &lock); + lock_strings(lock, &opt->pass_strings); + + ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &store); + if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); + ret = hx509_certs_init(context, "MEMORY:cert-pool", 0, NULL, &pool); + if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); + + certs_strings(context, "store", store, lock, &opt->certificate_strings); + certs_strings(context, "pool", pool, lock, &opt->pool_strings); + + if (opt->anchors_strings.num_strings) { + ret = hx509_certs_init(context, "MEMORY:cert-anchors", + 0, NULL, &anchors); + if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); + certs_strings(context, "anchors", anchors, lock, &opt->anchors_strings); + } else + anchors = NULL; + + if (opt->detached_signature_flag) + flags |= HX509_CMS_SIGNATURE_DETACHED; + if (opt->id_by_name_flag) + flags |= HX509_CMS_SIGNATURE_ID_NAME; + if (!opt->signer_flag) { + flags |= HX509_CMS_SIGNATURE_NO_SIGNER; + + } + + if (opt->signer_flag) { + ret = hx509_query_alloc(context, &q); + if (ret) + errx(1, "hx509_query_alloc: %d", ret); + + hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); + hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE); + + if (opt->signer_string) + hx509_query_match_friendly_name(q, opt->signer_string); + + ret = hx509_certs_filter(context, store, q, &signer); + hx509_query_free(context, q); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_find"); + } + if (!opt->embedded_certs_flag) + flags |= HX509_CMS_SIGNATURE_NO_CERTS; + if (opt->embed_leaf_only_flag) + flags |= HX509_CMS_SIGNATURE_LEAF_ONLY; + + ret = rk_undumpdata(infile, &p, &sz); + if (ret) + err(1, "map_file: %s: %d", infile, ret); + + if (opt->peer_alg_strings.num_strings) + peer_strings(context, &peer, &opt->peer_alg_strings); + + parse_oid(opt->content_type_string, &asn1_oid_id_pkcs7_data, &contentType); + + ret = hx509_cms_create_signed(context, + flags, + &contentType, + p, + sz, + NULL, + signer, + peer, + anchors, + pool, + &o); + if (ret) + hx509_err(context, 1, ret, "hx509_cms_create_signed: %d", ret); + + hx509_certs_free(&anchors); + hx509_certs_free(&pool); + hx509_certs_free(&store); + rk_xfree(p); + hx509_lock_free(lock); + hx509_peer_info_free(peer); + der_free_oid(&contentType); + + if (opt->content_info_flag) { + heim_octet_string wo; + + ret = hx509_cms_wrap_ContentInfo(&asn1_oid_id_pkcs7_signedData, &o, &wo); + if (ret) + errx(1, "hx509_cms_wrap_ContentInfo: %d", ret); + + der_free_octet_string(&o); + o = wo; + } + + if (opt->pem_flag) { + hx509_pem_header *header = NULL; + FILE *f; + + hx509_pem_add_header(&header, "Content-disposition", + opt->detached_signature_flag ? + "detached" : "inline"); + if (signer) { + ret = hx509_certs_iter_f(context, signer, print_signer, header); + if (ret) + hx509_err(context, 1, ret, "print signer"); + } + + f = fopen(outfile, "w"); + if (f == NULL) + err(1, "open %s", outfile); + + ret = hx509_pem_write(context, "CMS SIGNEDDATA", header, f, + o.data, o.length); + fclose(f); + hx509_pem_free_header(header); + if (ret) + errx(1, "hx509_pem_write: %d", ret); + + } else { + ret = _hx509_write_file(outfile, o.data, o.length); + if (ret) + errx(1, "hx509_write_file: %d", ret); + } + + hx509_certs_free(&signer); + free(o.data); + free(freeme); + + return 0; +} + +int +cms_unenvelope(struct cms_unenvelope_options *opt, int argc, char **argv) +{ + heim_oid contentType = { 0, NULL }; + heim_octet_string o, co; + hx509_certs certs; + size_t sz; + void *p; + int ret; + hx509_lock lock; + int flags = 0; + + hx509_lock_init(context, &lock); + lock_strings(lock, &opt->pass_strings); + + ret = rk_undumpdata(argv[0], &p, &sz); + if (ret) + err(1, "map_file: %s: %d", argv[0], ret); + + co.data = p; + co.length = sz; + + if (opt->content_info_flag) { + heim_octet_string uwco; + heim_oid oid; + + ret = hx509_cms_unwrap_ContentInfo(&co, &oid, &uwco, NULL); + if (ret) + errx(1, "hx509_cms_unwrap_ContentInfo: %d", ret); + + if (der_heim_oid_cmp(&oid, &asn1_oid_id_pkcs7_envelopedData) != 0) + errx(1, "Content is not SignedData"); + der_free_oid(&oid); + + co = uwco; + } + + ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs); + if (ret) + errx(1, "hx509_certs_init: MEMORY: %d", ret); + + certs_strings(context, "store", certs, lock, &opt->certificate_strings); + + if (opt->allow_weak_crypto_flag) + flags |= HX509_CMS_UE_ALLOW_WEAK; + + ret = hx509_cms_unenvelope(context, certs, flags, co.data, co.length, + NULL, 0, &contentType, &o); + if (co.data != p) + der_free_octet_string(&co); + if (ret) + hx509_err(context, 1, ret, "hx509_cms_unenvelope"); + + rk_xfree(p); + hx509_lock_free(lock); + hx509_certs_free(&certs); + der_free_oid(&contentType); + + ret = _hx509_write_file(argv[1], o.data, o.length); + if (ret) + errx(1, "hx509_write_file: %d", ret); + + der_free_octet_string(&o); + + return 0; +} + +int +cms_create_enveloped(struct cms_envelope_options *opt, int argc, char **argv) +{ + heim_oid contentType; + heim_octet_string o; + const heim_oid *enctype = NULL; + hx509_query *q; + hx509_certs certs; + hx509_cert cert; + int ret; + size_t sz; + void *p; + hx509_lock lock; + int flags = 0; + + memset(&contentType, 0, sizeof(contentType)); + + hx509_lock_init(context, &lock); + lock_strings(lock, &opt->pass_strings); + + ret = rk_undumpdata(argv[0], &p, &sz); + if (ret) + err(1, "map_file: %s: %d", argv[0], ret); + + ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs); + if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); + + certs_strings(context, "store", certs, lock, &opt->certificate_strings); + + if (opt->allow_weak_crypto_flag) + flags |= HX509_CMS_EV_ALLOW_WEAK; + + if (opt->encryption_type_string) { + enctype = hx509_crypto_enctype_by_name(opt->encryption_type_string); + if (enctype == NULL) + errx(1, "encryption type: %s no found", + opt->encryption_type_string); + } + + ret = hx509_query_alloc(context, &q); + if (ret) + errx(1, "hx509_query_alloc: %d", ret); + + hx509_query_match_option(q, HX509_QUERY_OPTION_KU_ENCIPHERMENT); + + ret = hx509_certs_find(context, certs, q, &cert); + hx509_query_free(context, q); + if (ret) + errx(1, "hx509_certs_find: %d", ret); + + parse_oid(opt->content_type_string, &asn1_oid_id_pkcs7_data, &contentType); + + ret = hx509_cms_envelope_1(context, flags, cert, p, sz, enctype, + &contentType, &o); + if (ret) + errx(1, "hx509_cms_envelope_1: %d", ret); + + hx509_cert_free(cert); + hx509_certs_free(&certs); + rk_xfree(p); + der_free_oid(&contentType); + + if (opt->content_info_flag) { + heim_octet_string wo; + + ret = hx509_cms_wrap_ContentInfo(&asn1_oid_id_pkcs7_envelopedData, &o, &wo); + if (ret) + errx(1, "hx509_cms_wrap_ContentInfo: %d", ret); + + der_free_octet_string(&o); + o = wo; + } + + hx509_lock_free(lock); + + ret = _hx509_write_file(argv[1], o.data, o.length); + if (ret) + errx(1, "hx509_write_file: %d", ret); + + der_free_octet_string(&o); + + return 0; +} + +static void +print_certificate(hx509_context hxcontext, hx509_cert cert, int verbose) +{ + const char *fn; + int ret; + + fn = hx509_cert_get_friendly_name(cert); + if (fn) + printf(" friendly name: %s\n", fn); + printf(" private key: %s\n", + _hx509_cert_private_key(cert) ? "yes" : "no"); + + ret = hx509_print_cert(hxcontext, cert, stdout); + if (ret) + errx(1, "failed to print cert"); + + if (verbose) { + hx509_validate_ctx vctx; + + hx509_validate_ctx_init(hxcontext, &vctx); + hx509_validate_ctx_set_print(vctx, hx509_print_stdout, stdout); + hx509_validate_ctx_add_flags(vctx, HX509_VALIDATE_F_VALIDATE); + hx509_validate_ctx_add_flags(vctx, HX509_VALIDATE_F_VERBOSE); + + hx509_validate_cert(hxcontext, vctx, cert); + + hx509_validate_ctx_free(vctx); + } +} + + +struct print_s { + int counter; + int verbose; +}; + +static int HX509_LIB_CALL +print_f(hx509_context hxcontext, void *ctx, hx509_cert cert) +{ + struct print_s *s = ctx; + + printf("cert: %d\n", s->counter++); + print_certificate(context, cert, s->verbose); + + return 0; +} + +static int HX509_LIB_CALL +print_fjson(hx509_context hxcontext, void *ctx, hx509_cert cert) +{ + const Certificate *c = NULL; + char *json = NULL; + + c = _hx509_get_cert(cert); + if (c) + json = print_Certificate(c, ASN1_PRINT_INDENT); + if (json) + printf("%s\n", json); + else + hx509_err(context, 1, errno, "Could not format certificate as JSON"); + free(json); + return 0; +} + + +int +pcert_print(struct print_options *opt, int argc, char **argv) +{ + hx509_certs certs; + hx509_lock lock; + struct print_s s; + + s.counter = 0; + s.verbose = opt->content_flag; + + hx509_lock_init(context, &lock); + lock_strings(lock, &opt->pass_strings); + + while(argc--) { + char *sn = fix_store_name(context, argv[0], "FILE"); + int ret; + + ret = hx509_certs_init(context, sn, 0, lock, &certs); + free(sn); + if (ret) { + if (opt->never_fail_flag) { + printf("ignoreing failure: %d\n", ret); + continue; + } + hx509_err(context, 1, ret, "hx509_certs_init"); + } + if (opt->raw_json_flag) { + hx509_certs_iter_f(context, certs, print_fjson, &s); + } else { + if (opt->info_flag) + hx509_certs_info(context, certs, NULL, NULL); + hx509_certs_iter_f(context, certs, print_f, &s); + } + hx509_certs_free(&certs); + argv++; + } + + hx509_lock_free(lock); + + return 0; +} + + +static int HX509_LIB_CALL +validate_f(hx509_context hxcontext, void *ctx, hx509_cert c) +{ + hx509_validate_cert(hxcontext, ctx, c); + return 0; +} + +int +pcert_validate(struct validate_options *opt, int argc, char **argv) +{ + hx509_validate_ctx ctx; + hx509_certs certs; + hx509_lock lock; + + hx509_lock_init(context, &lock); + lock_strings(lock, &opt->pass_strings); + + hx509_validate_ctx_init(context, &ctx); + hx509_validate_ctx_set_print(ctx, hx509_print_stdout, stdout); + hx509_validate_ctx_add_flags(ctx, HX509_VALIDATE_F_VALIDATE); + + while(argc--) { + char *sn = fix_store_name(context, argv[0], "FILE"); + int ret; + + ret = hx509_certs_init(context, sn, 0, lock, &certs); + if (ret) + errx(1, "hx509_certs_init: %d", ret); + hx509_certs_iter_f(context, certs, validate_f, ctx); + hx509_certs_free(&certs); + argv++; + free(sn); + } + hx509_validate_ctx_free(ctx); + + hx509_lock_free(lock); + + return 0; +} + +int +certificate_copy(struct certificate_copy_options *opt, int argc, char **argv) +{ + hx509_certs certs; + hx509_lock inlock, outlock = NULL; + char *sn; + int ret; + + hx509_lock_init(context, &inlock); + lock_strings(inlock, &opt->in_pass_strings); + + if (opt->out_pass_string) { + hx509_lock_init(context, &outlock); + ret = hx509_lock_command_string(outlock, opt->out_pass_string); + if (ret) + errx(1, "hx509_lock_command_string: %s: %d", + opt->out_pass_string, ret); + } + + sn = fix_store_name(context, argv[argc - 1], "FILE"); + ret = hx509_certs_init(context, sn, + HX509_CERTS_CREATE, inlock, &certs); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_init %s", sn); + free(sn); + + while(argc-- > 1) { + int retx; + + sn = fix_store_name(context, argv[0], "FILE"); + retx = hx509_certs_append(context, certs, inlock, sn); + if (retx) + hx509_err(context, 1, retx, "hx509_certs_append %s", sn); + free(sn); + argv++; + } + + ret = hx509_certs_store(context, certs, 0, outlock); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_store"); + + hx509_certs_free(&certs); + hx509_lock_free(inlock); + hx509_lock_free(outlock); + + return 0; +} + +struct verify { + hx509_verify_ctx ctx; + hx509_certs chain; + const char *hostname; + int errors; + int count; +}; + +static int HX509_LIB_CALL +verify_f(hx509_context hxcontext, void *ctx, hx509_cert c) +{ + struct verify *v = ctx; + int ret; + + ret = hx509_verify_path(hxcontext, v->ctx, c, v->chain); + if (ret) { + char *s = hx509_get_error_string(hxcontext, ret); + printf("verify_path: %s: %d\n", s, ret); + hx509_free_error_string(s); + v->errors++; + } else { + v->count++; + printf("path ok\n"); + } + + if (v->hostname) { + ret = hx509_verify_hostname(hxcontext, c, 0, HX509_HN_HOSTNAME, + v->hostname, NULL, 0); + if (ret) { + printf("verify_hostname: %d\n", ret); + v->errors++; + } + } + + return 0; +} + +int +pcert_verify(struct verify_options *opt, int argc, char **argv) +{ + hx509_certs anchors, chain, certs; + hx509_revoke_ctx revoke_ctx; + hx509_verify_ctx ctx; + struct verify v; + int ret; + + memset(&v, 0, sizeof(v)); + + if (opt->missing_revoke_flag) + hx509_context_set_missing_revoke(context, 1); + + ret = hx509_verify_init_ctx(context, &ctx); + if (ret) + hx509_err(context, 1, ret, "hx509_verify_init_ctx"); + ret = hx509_certs_init(context, "MEMORY:anchors", 0, NULL, &anchors); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); + ret = hx509_certs_init(context, "MEMORY:chain", 0, NULL, &chain); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); + ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &certs); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); + + if (opt->allow_proxy_certificate_flag) + hx509_verify_set_proxy_certificate(ctx, 1); + + if (opt->time_string) { + const char *p; + struct tm tm; + time_t t; + + memset(&tm, 0, sizeof(tm)); + + p = strptime (opt->time_string, "%Y-%m-%d", &tm); + if (p == NULL) + errx(1, "Failed to parse time %s, need to be on format %%Y-%%m-%%d", + opt->time_string); + + t = tm2time (tm, 0); + + hx509_verify_set_time(ctx, t); + } + + if (opt->hostname_string) + v.hostname = opt->hostname_string; + if (opt->max_depth_integer) + hx509_verify_set_max_depth(ctx, opt->max_depth_integer); + + ret = hx509_revoke_init(context, &revoke_ctx); + if (ret) + errx(1, "hx509_revoke_init: %d", ret); + + while(argc--) { + const char *s = *argv++; + char *sn = NULL; + + if (strncmp(s, "chain:", 6) == 0) { + s += 6; + + sn = fix_store_name(context, s, "FILE"); + ret = hx509_certs_append(context, chain, NULL, sn); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_append: chain: %s: %d", + sn, ret); + + } else if (strncmp(s, "anchor:", 7) == 0) { + s += 7; + + sn = fix_store_name(context, s, "FILE"); + ret = hx509_certs_append(context, anchors, NULL, sn); + if (ret) + hx509_err(context, 1, ret, + "hx509_certs_append: anchor: %s: %d", sn, ret); + + } else if (strncmp(s, "cert:", 5) == 0) { + s += 5; + + sn = fix_store_name(context, s, "FILE"); + ret = hx509_certs_append(context, certs, NULL, sn); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_append: certs: %s: %d", + sn, ret); + + } else if (strncmp(s, "crl:", 4) == 0) { + s += 4; + + ret = hx509_revoke_add_crl(context, revoke_ctx, s); + if (ret) + errx(1, "hx509_revoke_add_crl: %s: %d", s, ret); + + } else if (strncmp(s, "ocsp:", 5) == 0) { + s += 5; + + ret = hx509_revoke_add_ocsp(context, revoke_ctx, s); + if (ret) + errx(1, "hx509_revoke_add_ocsp: %s: %d", s, ret); + + } else { + errx(1, "unknown option to verify: `%s'\n", s); + } + free(sn); + } + + hx509_verify_attach_anchors(ctx, anchors); + hx509_verify_attach_revoke(ctx, revoke_ctx); + + v.ctx = ctx; + v.chain = chain; + + hx509_certs_iter_f(context, certs, verify_f, &v); + + hx509_verify_destroy_ctx(ctx); + + hx509_certs_free(&certs); + hx509_certs_free(&chain); + hx509_certs_free(&anchors); + + hx509_revoke_free(&revoke_ctx); + + + if (v.count == 0) { + printf("no certs verify at all\n"); + return 1; + } + + if (v.errors) { + printf("failed verifing %d checks\n", v.errors); + return 1; + } + + return 0; +} + +int +query(struct query_options *opt, int argc, char **argv) +{ + hx509_lock lock; + hx509_query *q; + hx509_certs certs; + hx509_cert c; + int ret; + + ret = hx509_query_alloc(context, &q); + if (ret) + errx(1, "hx509_query_alloc: %d", ret); + + hx509_lock_init(context, &lock); + lock_strings(lock, &opt->pass_strings); + + ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs); + if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); + + while (argc > 0) { + char *sn = fix_store_name(context, argv[0], "FILE"); + + ret = hx509_certs_append(context, certs, lock, sn); + if (ret) + errx(1, "hx509_certs_append: %s: %d", sn, ret); + free(sn); + + argc--; + argv++; + } + + if (opt->friendlyname_string) + hx509_query_match_friendly_name(q, opt->friendlyname_string); + + if (opt->eku_string) { + heim_oid oid; + + parse_oid(opt->eku_string, NULL, &oid); + + ret = hx509_query_match_eku(q, &oid); + if (ret) + errx(1, "hx509_query_match_eku: %d", ret); + der_free_oid(&oid); + } + + if (opt->private_key_flag) + hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); + + if (opt->keyEncipherment_flag) + hx509_query_match_option(q, HX509_QUERY_OPTION_KU_ENCIPHERMENT); + + if (opt->digitalSignature_flag) + hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE); + + if (opt->expr_string) + hx509_query_match_expr(context, q, opt->expr_string); + + ret = hx509_certs_find(context, certs, q, &c); + hx509_query_free(context, q); + if (ret) + printf("no match found (%d)\n", ret); + else { + printf("match found\n"); + if (opt->print_flag) + print_certificate(context, c, 0); + } + + hx509_cert_free(c); + hx509_certs_free(&certs); + + hx509_lock_free(lock); + + return ret; +} + +int +ocsp_fetch(struct ocsp_fetch_options *opt, int argc, char **argv) +{ + hx509_certs reqcerts, pool; + heim_octet_string req, nonce_data, *nonce = &nonce_data; + hx509_lock lock; + int i, ret; + char *file; + const char *url = "/"; + + memset(&nonce, 0, sizeof(nonce)); + + hx509_lock_init(context, &lock); + lock_strings(lock, &opt->pass_strings); + + /* no nonce */ + if (!opt->nonce_flag) + nonce = NULL; + + if (opt->url_path_string) + url = opt->url_path_string; + + ret = hx509_certs_init(context, "MEMORY:ocsp-pool", 0, NULL, &pool); + if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); + + certs_strings(context, "ocsp-pool", pool, lock, &opt->pool_strings); + + file = argv[0]; + + ret = hx509_certs_init(context, "MEMORY:ocsp-req", 0, NULL, &reqcerts); + if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); + + for (i = 1; i < argc; i++) { + char *sn = fix_store_name(context, argv[i], "FILE"); + + ret = hx509_certs_append(context, reqcerts, lock, sn); + if (ret) + errx(1, "hx509_certs_append: req: %s: %d", sn, ret); + free(sn); + } + + ret = hx509_ocsp_request(context, reqcerts, pool, NULL, NULL, &req, nonce); + if (ret) + errx(1, "hx509_ocsp_request: req: %d", ret); + + { + FILE *f; + + f = fopen(file, "w"); + if (f == NULL) + abort(); + + fprintf(f, + "POST %s HTTP/1.0\r\n" + "Content-Type: application/ocsp-request\r\n" + "Content-Length: %ld\r\n" + "\r\n", + url, + (unsigned long)req.length); + fwrite(req.data, req.length, 1, f); + fclose(f); + } + + if (nonce) + der_free_octet_string(nonce); + + hx509_certs_free(&reqcerts); + hx509_certs_free(&pool); + + return 0; +} + +int +ocsp_print(struct ocsp_print_options *opt, int argc, char **argv) +{ + hx509_revoke_ocsp_print(context, argv[0], stdout); + return 0; +} + +int +revoke_print(struct revoke_print_options *opt, int argc, char **argv) +{ + hx509_revoke_ctx revoke_ctx; + int ret; + + ret = hx509_revoke_init(context, &revoke_ctx); + if (ret) + errx(1, "hx509_revoke_init: %d", ret); + + while(argc--) { + char *s = *argv++; + + if (strncmp(s, "crl:", 4) == 0) { + s += 4; + + ret = hx509_revoke_add_crl(context, revoke_ctx, s); + if (ret) + errx(1, "hx509_revoke_add_crl: %s: %d", s, ret); + + } else if (strncmp(s, "ocsp:", 5) == 0) { + s += 5; + + ret = hx509_revoke_add_ocsp(context, revoke_ctx, s); + if (ret) + errx(1, "hx509_revoke_add_ocsp: %s: %d", s, ret); + + } else { + errx(1, "unknown option to verify: `%s'\n", s); + } + } + + ret = hx509_revoke_print(context, revoke_ctx, stdout); + if (ret) + warnx("hx509_revoke_print: %d", ret); + + hx509_revoke_free(&revoke_ctx); + return ret; +} + +/* + * + */ + +static int HX509_LIB_CALL +verify_o(hx509_context hxcontext, void *ctx, hx509_cert c) +{ + heim_octet_string *os = ctx; + time_t expiration; + int ret; + + ret = hx509_ocsp_verify(context, 0, c, 0, + os->data, os->length, &expiration); + if (ret) { + char *s = hx509_get_error_string(hxcontext, ret); + printf("ocsp_verify: %s: %d\n", s, ret); + hx509_free_error_string(s); + } else + printf("expire: %d\n", (int)expiration); + + return ret; +} + + +int +ocsp_verify(struct ocsp_verify_options *opt, int argc, char **argv) +{ + hx509_lock lock; + hx509_certs certs; + int ret, i; + heim_octet_string os; + + hx509_lock_init(context, &lock); + + if (opt->ocsp_file_string == NULL) + errx(1, "no ocsp file given"); + + ret = _hx509_map_file_os(opt->ocsp_file_string, &os); + if (ret) + err(1, "map_file: %s: %d", argv[0], ret); + + ret = hx509_certs_init(context, "MEMORY:test-certs", 0, NULL, &certs); + if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); + + for (i = 0; i < argc; i++) { + char *sn = fix_store_name(context, argv[i], "FILE"); + + ret = hx509_certs_append(context, certs, lock, sn); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_append: %s", sn); + free(sn); + } + + ret = hx509_certs_iter_f(context, certs, verify_o, &os); + + hx509_certs_free(&certs); + _hx509_unmap_file_os(&os); + hx509_lock_free(lock); + + return ret; +} + +static int +read_private_key(const char *fn, hx509_private_key *key) +{ + hx509_private_key *keys; + hx509_certs certs; + char *sn = fix_store_name(context, fn, "FILE"); + int ret; + + *key = NULL; + + ret = hx509_certs_init(context, sn, 0, NULL, &certs); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_init: %s", sn); + + ret = _hx509_certs_keys_get(context, certs, &keys); + hx509_certs_free(&certs); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_keys_get"); + if (keys[0] == NULL) + errx(1, "no keys in key store: %s", sn); + free(sn); + + *key = _hx509_private_key_ref(keys[0]); + _hx509_certs_keys_free(context, keys); + + return 0; +} + +static void +get_key(const char *fn, const char *type, int optbits, + hx509_private_key *signer) +{ + int ret = 0; + + if (type) { + struct hx509_generate_private_context *gen_ctx = NULL; + + if (strcasecmp(type, "rsa") != 0) + errx(1, "can only handle rsa keys for now"); + + ret = _hx509_generate_private_key_init(context, + ASN1_OID_ID_PKCS1_RSAENCRYPTION, + &gen_ctx); + if (ret == 0) + ret = _hx509_generate_private_key_bits(context, gen_ctx, optbits); + if (ret == 0) + ret = _hx509_generate_private_key(context, gen_ctx, signer); + _hx509_generate_private_key_free(&gen_ctx); + if (ret) + hx509_err(context, 1, ret, "failed to generate private key of type %s", type); + + if (fn) { + char *sn = fix_store_name(context, fn, "FILE"); + hx509_certs certs = NULL; + hx509_cert cert = NULL; + + cert = hx509_cert_init_private_key(context, *signer, NULL); + if (cert) + ret = hx509_certs_init(context, sn, + HX509_CERTS_CREATE | + HX509_CERTS_UNPROTECT_ALL, + NULL, &certs); + if (ret == 0) + ret = hx509_certs_add(context, certs, cert); + if (ret == 0) + ret = hx509_certs_store(context, certs, 0, NULL); + if (ret) + hx509_err(context, 1, ret, "failed to store generated private " + "key in %s", sn); + + if (certs) + hx509_certs_free(&certs); + if (cert) + hx509_cert_free(cert); + free(sn); + } + } else { + if (fn == NULL) + err(1, "no private key"); + ret = read_private_key(fn, signer); + if (ret) + hx509_err(context, 1, ret, "failed to read private key from %s", + fn); + } +} + +int +generate_key(struct generate_key_options *opt, int argc, char **argv) +{ + hx509_private_key signer; + const char *type = opt->type_string ? opt->type_string : "rsa"; + int bits = opt->key_bits_integer ? opt->key_bits_integer : 2048; + + memset(&signer, 0, sizeof(signer)); + get_key(argv[0], type, bits, &signer); + hx509_private_key_free(&signer); + return 0; +} + +int +request_create(struct request_create_options *opt, int argc, char **argv) +{ + heim_octet_string request; + hx509_request req; + int ret, i; + hx509_private_key signer; + SubjectPublicKeyInfo key; + const char *outfile = argv[0]; + + memset(&key, 0, sizeof(key)); + memset(&signer, 0, sizeof(signer)); + + get_key(opt->key_string, + opt->generate_key_string, + opt->key_bits_integer, + &signer); + + hx509_request_init(context, &req); + + if (opt->subject_string) { + hx509_name name = NULL; + + ret = hx509_parse_name(context, opt->subject_string, &name); + if (ret) + errx(1, "hx509_parse_name: %d\n", ret); + hx509_request_set_name(context, req, name); + + if (opt->verbose_flag) { + char *s; + hx509_name_to_string(name, &s); + printf("%s\n", s); + free(s); + } + hx509_name_free(&name); + } + + for (i = 0; i < opt->email_strings.num_strings; i++) { + ret = hx509_request_add_email(context, req, + opt->email_strings.strings[i]); + if (ret) + hx509_err(context, 1, ret, "hx509_request_add_email"); + } + + for (i = 0; i < opt->jid_strings.num_strings; i++) { + ret = hx509_request_add_xmpp_name(context, req, + opt->jid_strings.strings[i]); + if (ret) + hx509_err(context, 1, ret, "hx509_request_add_xmpp_name"); + } + + for (i = 0; i < opt->dnsname_strings.num_strings; i++) { + ret = hx509_request_add_dns_name(context, req, + opt->dnsname_strings.strings[i]); + if (ret) + hx509_err(context, 1, ret, "hx509_request_add_dns_name"); + } + + for (i = 0; i < opt->kerberos_strings.num_strings; i++) { + ret = hx509_request_add_pkinit(context, req, + opt->kerberos_strings.strings[i]); + if (ret) + hx509_err(context, 1, ret, "hx509_request_add_pkinit"); + } + + for (i = 0; i < opt->ms_kerberos_strings.num_strings; i++) { + ret = hx509_request_add_ms_upn_name(context, req, + opt->ms_kerberos_strings.strings[i]); + if (ret) + hx509_err(context, 1, ret, "hx509_request_add_ms_upn_name"); + } + + for (i = 0; i < opt->registered_strings.num_strings; i++) { + heim_oid oid; + + parse_oid(opt->registered_strings.strings[i], NULL, &oid); + ret = hx509_request_add_registered(context, req, &oid); + der_free_oid(&oid); + if (ret) + hx509_err(context, 1, ret, "hx509_request_add_registered"); + } + + for (i = 0; i < opt->eku_strings.num_strings; i++) { + heim_oid oid; + + parse_oid(opt->eku_strings.strings[i], NULL, &oid); + ret = hx509_request_add_eku(context, req, &oid); + der_free_oid(&oid); + if (ret) + hx509_err(context, 1, ret, "hx509_request_add_eku"); + } + + + ret = hx509_private_key2SPKI(context, signer, &key); + if (ret) + errx(1, "hx509_private_key2SPKI: %d\n", ret); + + ret = hx509_request_set_SubjectPublicKeyInfo(context, + req, + &key); + free_SubjectPublicKeyInfo(&key); + if (ret) + hx509_err(context, 1, ret, "hx509_request_set_SubjectPublicKeyInfo"); + + ret = hx509_request_to_pkcs10(context, + req, + signer, + &request); + if (ret) + hx509_err(context, 1, ret, "hx509_request_to_pkcs10"); + + hx509_private_key_free(&signer); + hx509_request_free(&req); + + if (ret == 0) + rk_dumpdata(outfile, request.data, request.length); + der_free_octet_string(&request); + + return 0; +} + +int +request_print(struct request_print_options *opt, int argc, char **argv) +{ + int ret, i; + + printf("request print\n"); + + for (i = 0; i < argc; i++) { + hx509_request req; + char *cn = fix_csr_name(argv[i], "PKCS10"); + + ret = hx509_request_parse(context, cn, &req); + if (ret) + hx509_err(context, 1, ret, "parse_request: %s", cn); + + ret = hx509_request_print(context, req, stdout); + hx509_request_free(&req); + if (ret) + hx509_err(context, 1, ret, "Failed to print file %s", cn); + free(cn); + } + + return 0; +} + +int +info(void *opt, int argc, char **argv) +{ + + ENGINE_add_conf_module(); + + { + const RSA_METHOD *m = RSA_get_default_method(); + if (m != NULL) + printf("rsa: %s\n", m->name); + } + { + const DH_METHOD *m = DH_get_default_method(); + if (m != NULL) + printf("dh: %s\n", m->name); + } +#ifdef HAVE_HCRYPTO_W_OPENSSL + { + printf("ecdsa: ECDSA_METHOD-not-export\n"); + } +#else + { + printf("ecdsa: hcrypto null\n"); + } +#endif + { + int ret = RAND_status(); + printf("rand: %s\n", ret == 1 ? "ok" : "not available"); + } + + return 0; +} + +int +random_data(void *opt, int argc, char **argv) +{ + void *ptr; + ssize_t len; + int ret; + + len = parse_bytes(argv[0], "byte"); + if (len <= 0) { + fprintf(stderr, "bad argument to random-data\n"); + return 1; + } + + ptr = malloc(len); + if (ptr == NULL) { + fprintf(stderr, "out of memory\n"); + return 1; + } + + ret = RAND_bytes(ptr, len); + if (ret != 1) { + free(ptr); + fprintf(stderr, "did not get cryptographic strong random\n"); + return 1; + } + + fwrite(ptr, len, 1, stdout); + fflush(stdout); + + free(ptr); + + return 0; +} + +int +crypto_available(struct crypto_available_options *opt, int argc, char **argv) +{ + AlgorithmIdentifier *val; + unsigned int len, i; + int ret, type = HX509_SELECT_ALL; + + if (opt->type_string) { + if (strcmp(opt->type_string, "all") == 0) + type = HX509_SELECT_ALL; + else if (strcmp(opt->type_string, "digest") == 0) + type = HX509_SELECT_DIGEST; + else if (strcmp(opt->type_string, "public-sig") == 0) + type = HX509_SELECT_PUBLIC_SIG; + else if (strcmp(opt->type_string, "secret") == 0) + type = HX509_SELECT_SECRET_ENC; + else + errx(1, "unknown type: %s", opt->type_string); + } + + ret = hx509_crypto_available(context, type, NULL, &val, &len); + if (ret) + errx(1, "hx509_crypto_available"); + + for (i = 0; i < len; i++) { + char *s; + if (opt->oid_syms_flag) + der_print_heim_oid_sym(&val[i].algorithm, '.', &s); + else + der_print_heim_oid(&val[i].algorithm, '.', &s); + printf("%s\n", s); + free(s); + } + + hx509_crypto_free_algs(val, len); + + return 0; +} + +int +crypto_select(struct crypto_select_options *opt, int argc, char **argv) +{ + hx509_peer_info peer = NULL; + AlgorithmIdentifier selected; + int ret, type = HX509_SELECT_DIGEST; + char *s; + + if (opt->type_string) { + if (strcmp(opt->type_string, "digest") == 0) + type = HX509_SELECT_DIGEST; + else if (strcmp(opt->type_string, "public-sig") == 0) + type = HX509_SELECT_PUBLIC_SIG; + else if (strcmp(opt->type_string, "secret") == 0) + type = HX509_SELECT_SECRET_ENC; + else + errx(1, "unknown type: %s", opt->type_string); + } + + if (opt->peer_cmstype_strings.num_strings) + peer_strings(context, &peer, &opt->peer_cmstype_strings); + + ret = hx509_crypto_select(context, type, NULL, peer, &selected); + if (ret) + errx(1, "hx509_crypto_available"); + + if (opt->oid_sym_flag) + der_print_heim_oid_sym(&selected.algorithm, '.', &s); + else + der_print_heim_oid(&selected.algorithm, '.', &s); + printf("%s\n", s); + free(s); + free_AlgorithmIdentifier(&selected); + + hx509_peer_info_free(peer); + + return 0; +} + +int +hxtool_hex(struct hex_options *opt, int argc, char **argv) +{ + + if (opt->decode_flag) { + char buf[1024], buf2[1024], *p; + ssize_t len; + + while(fgets(buf, sizeof(buf), stdin) != NULL) { + buf[strcspn(buf, "\r\n")] = '\0'; + p = buf; + while(isspace(*(unsigned char *)p)) + p++; + len = hex_decode(p, buf2, strlen(p)); + if (len < 0) + errx(1, "hex_decode failed"); + if (fwrite(buf2, 1, len, stdout) != (size_t)len) + errx(1, "fwrite failed"); + } + } else { + char buf[28], *p; + ssize_t len; + + while((len = fread(buf, 1, sizeof(buf), stdin)) != 0) { + len = hex_encode(buf, len, &p); + if (len < 0) + continue; + fprintf(stdout, "%s\n", p); + free(p); + } + } + return 0; +} + +struct cert_type_opt { + int pkinit; +}; + + +static int +https_server(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) +{ + return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_serverAuth); +} + +static int +https_negotiate_server(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) +{ + int ret = hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkekuoid); + if (ret == 0) + ret = hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_serverAuth); + opt->pkinit++; + return ret; +} + +static int +https_client(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) +{ + return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_clientAuth); +} + +static int +peap_server(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) +{ + return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_serverAuth); +} + +static int +pkinit_kdc(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) +{ + opt->pkinit++; + return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkkdcekuoid); +} + +static int +pkinit_client(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) +{ + int ret; + + opt->pkinit++; + + ret = hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkekuoid); + if (ret) + return ret; + + ret = hx509_ca_tbs_add_eku(context, tbs, &asn1_oid_id_pkix_kp_clientAuth); + if (ret) + return ret; + + return hx509_ca_tbs_add_eku(context, tbs, &asn1_oid_id_pkinit_ms_eku); +} + +static int +email_client(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) +{ + return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_emailProtection); +} + +struct { + const char *type; + const char *desc; + int (*eval)(hx509_context, hx509_ca_tbs, struct cert_type_opt *); +} certtypes[] = { + { + "https-server", + "Used for HTTPS server and many other TLS server certificate types", + https_server + }, + { + "https-client", + "Used for HTTPS client certificates", + https_client + }, + { + "email-client", + "Certificate will be use for email", + email_client + }, + { + "pkinit-client", + "Certificate used for Kerberos PK-INIT client certificates", + pkinit_client + }, + { + "pkinit-kdc", + "Certificates used for Kerberos PK-INIT KDC certificates", + pkinit_kdc + }, + { + "https-negotiate-server", + "Used for HTTPS server and many other TLS server certificate types", + https_negotiate_server + }, + { + "peap-server", + "Certificate used for Radius PEAP (Protected EAP)", + peap_server + } +}; + +static void +print_eval_types(FILE *out) +{ + rtbl_t table; + unsigned i; + + table = rtbl_create(); + rtbl_add_column_by_id (table, 0, "Name", 0); + rtbl_add_column_by_id (table, 1, "Description", 0); + + for (i = 0; i < sizeof(certtypes)/sizeof(certtypes[0]); i++) { + rtbl_add_column_entry_by_id(table, 0, certtypes[i].type); + rtbl_add_column_entry_by_id(table, 1, certtypes[i].desc); + } + + rtbl_format (table, out); + rtbl_destroy (table); +} + +static int +eval_types(hx509_context contextp, + hx509_ca_tbs tbs, + const struct certificate_sign_options *opt) +{ + struct cert_type_opt ctopt; + int i; + size_t j; + int ret; + + memset(&ctopt, 0, sizeof(ctopt)); + + for (i = 0; i < opt->type_strings.num_strings; i++) { + const char *type = opt->type_strings.strings[i]; + + for (j = 0; j < sizeof(certtypes)/sizeof(certtypes[0]); j++) { + if (strcasecmp(type, certtypes[j].type) == 0) { + ret = (*certtypes[j].eval)(contextp, tbs, &ctopt); + if (ret) + hx509_err(contextp, 1, ret, + "Failed to evaluate cert type %s", type); + break; + } + } + if (j >= sizeof(certtypes)/sizeof(certtypes[0])) { + fprintf(stderr, "Unknown certificate type %s\n\n", type); + fprintf(stderr, "Available types:\n"); + print_eval_types(stderr); + exit(1); + } + } + + for (i = 0; i < opt->pk_init_principal_strings.num_strings; i++) { + const char *pk_init_princ = opt->pk_init_principal_strings.strings[i]; + + if (!ctopt.pkinit) + errx(1, "pk-init principal given but no pk-init oid"); + + ret = hx509_ca_tbs_add_san_pkinit(contextp, tbs, pk_init_princ); + if (ret) + hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_pkinit"); + } + + if (opt->ms_upn_string) { + if (!ctopt.pkinit) + errx(1, "MS upn given but no pk-init oid"); + + ret = hx509_ca_tbs_add_san_ms_upn(contextp, tbs, opt->ms_upn_string); + if (ret) + hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_ms_upn"); + } + + + for (i = 0; i < opt->hostname_strings.num_strings; i++) { + const char *hostname = opt->hostname_strings.strings[i]; + + ret = hx509_ca_tbs_add_san_hostname(contextp, tbs, hostname); + if (ret) + hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_hostname"); + } + + for (i = 0; i < opt->dnssrv_strings.num_strings; i++) { + const char *dnssrv = opt->dnssrv_strings.strings[i]; + + ret = hx509_ca_tbs_add_san_dnssrv(contextp, tbs, dnssrv); + if (ret) + hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_dnssrv"); + } + + for (i = 0; i < opt->email_strings.num_strings; i++) { + const char *email = opt->email_strings.strings[i]; + + ret = hx509_ca_tbs_add_san_rfc822name(contextp, tbs, email); + if (ret) + hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_hostname"); + + ret = hx509_ca_tbs_add_eku(contextp, tbs, + &asn1_oid_id_pkix_kp_emailProtection); + if (ret) + hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_eku"); + } + + if (opt->jid_string) { + ret = hx509_ca_tbs_add_san_jid(contextp, tbs, opt->jid_string); + if (ret) + hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_jid"); + } + + return 0; +} + +int +hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv) +{ + int ret; + hx509_ca_tbs tbs; + hx509_cert signer = NULL, cert = NULL; + hx509_private_key private_key = NULL; + hx509_private_key cert_key = NULL; + hx509_name subject = NULL; + SubjectPublicKeyInfo spki; + heim_oid oid; + size_t i; + int delta = 0; + + memset(&oid, 0, sizeof(oid)); + memset(&spki, 0, sizeof(spki)); + + if (opt->ca_certificate_string == NULL && !opt->self_signed_flag) + errx(1, "--ca-certificate argument missing (not using --self-signed)"); + if (opt->ca_private_key_string == NULL && opt->generate_key_string == NULL && opt->self_signed_flag) + errx(1, "--ca-private-key argument missing (using --self-signed)"); + if (opt->certificate_string == NULL) + errx(1, "--certificate argument missing"); + + if (opt->template_certificate_string && opt->template_fields_string == NULL) + errx(1, "--template-certificate used but no --template-fields given"); + + if (opt->lifetime_string) { + delta = parse_time(opt->lifetime_string, "day"); + if (delta < 0) + errx(1, "Invalid lifetime: %s", opt->lifetime_string); + } + + if (opt->ca_certificate_string) { + hx509_certs cacerts = NULL; + hx509_query *q; + char *sn = fix_store_name(context, opt->ca_certificate_string, "FILE"); + + ret = hx509_certs_init(context, sn, 0, NULL, &cacerts); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_init: %s", sn); + + ret = hx509_query_alloc(context, &q); + if (ret) + errx(1, "hx509_query_alloc: %d", ret); + + hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); + if (!opt->issue_proxy_flag) + hx509_query_match_option(q, HX509_QUERY_OPTION_KU_KEYCERTSIGN); + + ret = hx509_certs_find(context, cacerts, q, &signer); + hx509_query_free(context, q); + hx509_certs_free(&cacerts); + if (ret) + hx509_err(context, 1, ret, "no CA certificate found"); + free(sn); + } else if (opt->self_signed_flag) { + if (opt->generate_key_string == NULL + && opt->ca_private_key_string == NULL) + errx(1, "no signing private key"); + + if (opt->req_string) + errx(1, "can't be self-signing and have a request at the same time"); + } else + errx(1, "missing ca key"); + + if (opt->ca_private_key_string) { + + ret = read_private_key(opt->ca_private_key_string, &private_key); + if (ret) + err(1, "read_private_key"); + + ret = hx509_private_key2SPKI(context, private_key, &spki); + if (ret) + errx(1, "hx509_private_key2SPKI: %d\n", ret); + + if (opt->self_signed_flag) + cert_key = private_key; + } + + if (opt->req_string) { + hx509_request req; + char *cn = fix_csr_name(opt->req_string, "PKCS10"); + + /* + * Extract the CN and other attributes we want to preserve from the + * requested subjectName and then set them in the hx509_env for the + * template. + */ + ret = hx509_request_parse(context, cn, &req); + if (ret) + hx509_err(context, 1, ret, "parse_request: %s", cn); + ret = hx509_request_get_name(context, req, &subject); + if (ret) + hx509_err(context, 1, ret, "get name"); + ret = hx509_request_get_SubjectPublicKeyInfo(context, req, &spki); + if (ret) + hx509_err(context, 1, ret, "get spki"); + hx509_request_free(&req); + free(cn); + } + + if (opt->generate_key_string) { + struct hx509_generate_private_context *keyctx; + + ret = _hx509_generate_private_key_init(context, + &asn1_oid_id_pkcs1_rsaEncryption, + &keyctx); + if (ret) + hx509_err(context, 1, ret, "generate private key"); + + if (opt->issue_ca_flag) + _hx509_generate_private_key_is_ca(context, keyctx); + + if (opt->key_bits_integer) + _hx509_generate_private_key_bits(context, keyctx, + opt->key_bits_integer); + + ret = _hx509_generate_private_key(context, keyctx, + &cert_key); + _hx509_generate_private_key_free(&keyctx); + if (ret) + hx509_err(context, 1, ret, "generate private key"); + + ret = hx509_private_key2SPKI(context, cert_key, &spki); + if (ret) + errx(1, "hx509_private_key2SPKI: %d\n", ret); + + if (opt->self_signed_flag) + private_key = cert_key; + } + + if (opt->certificate_private_key_string) { + ret = read_private_key(opt->certificate_private_key_string, &cert_key); + if (ret) + err(1, "read_private_key for certificate"); + } + + if (opt->subject_string) { + if (subject) + hx509_name_free(&subject); + ret = hx509_parse_name(context, opt->subject_string, &subject); + if (ret) + hx509_err(context, 1, ret, "hx509_parse_name"); + } + + /* + * + */ + + ret = hx509_ca_tbs_init(context, &tbs); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_init"); + + for (i = 0; i < opt->eku_strings.num_strings; i++) { + parse_oid(opt->eku_strings.strings[i], NULL, &oid); + ret = hx509_ca_tbs_add_eku(context, tbs, &oid); + if (ret) + hx509_err(context, 1, ret, "hx509_request_add_eku"); + der_free_oid(&oid); + } + if (opt->ku_strings.num_strings) { + const struct units *kus = asn1_KeyUsage_units(); + const struct units *kup; + uint64_t n = 0; + + for (i = 0; i < opt->ku_strings.num_strings; i++) { + for (kup = kus; kup->name; kup++) { + if (strcmp(kup->name, opt->ku_strings.strings[i])) + continue; + n |= kup->mult; + break; + } + } + ret = hx509_ca_tbs_add_ku(context, tbs, int2KeyUsage(n)); + if (ret) + hx509_err(context, 1, ret, "hx509_request_add_ku"); + } + if (opt->signature_algorithm_string) { + const AlgorithmIdentifier *sigalg; + if (strcasecmp(opt->signature_algorithm_string, "rsa-with-sha1") == 0) + sigalg = hx509_signature_rsa_with_sha1(); + else if (strcasecmp(opt->signature_algorithm_string, "rsa-with-sha256") == 0) + sigalg = hx509_signature_rsa_with_sha256(); + else + errx(1, "unsupported sigature algorithm"); + hx509_ca_tbs_set_signature_algorithm(context, tbs, sigalg); + } + + if (opt->template_certificate_string) { + hx509_cert template; + hx509_certs tcerts; + char *sn = fix_store_name(context, opt->template_certificate_string, + "FILE"); + int flags; + + ret = hx509_certs_init(context, sn, 0, NULL, &tcerts); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_init: %s", sn); + + ret = hx509_get_one_cert(context, tcerts, &template); + + hx509_certs_free(&tcerts); + if (ret) + hx509_err(context, 1, ret, "no template certificate found"); + + flags = parse_units(opt->template_fields_string, + hx509_ca_tbs_template_units(), ""); + + ret = hx509_ca_tbs_set_template(context, tbs, flags, template); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_set_template"); + + hx509_cert_free(template); + free(sn); + } + + if (opt->serial_number_string) { + heim_integer serialNumber; + + ret = der_parse_hex_heim_integer(opt->serial_number_string, + &serialNumber); + if (ret) + err(1, "der_parse_hex_heim_integer"); + ret = hx509_ca_tbs_set_serialnumber(context, tbs, &serialNumber); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_init"); + der_free_heim_integer(&serialNumber); + } + + if (spki.subjectPublicKey.length) { + ret = hx509_ca_tbs_set_spki(context, tbs, &spki); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_set_spki"); + } + + if (subject) { + ret = hx509_ca_tbs_set_subject(context, tbs, subject); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_set_subject"); + } + + if (opt->crl_uri_string) { + ret = hx509_ca_tbs_add_crl_dp_uri(context, tbs, + opt->crl_uri_string, NULL); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_add_crl_dp_uri"); + } + + eval_types(context, tbs, opt); + + if (opt->permanent_id_string) { + ret = hx509_ca_tbs_add_san_permanentIdentifier_string(context, tbs, + opt->permanent_id_string); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_permanentIdentifier"); + } + + if (opt->hardware_module_name_string) { + ret = hx509_ca_tbs_add_san_hardwareModuleName_string(context, tbs, + opt->hardware_module_name_string); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_hardwareModuleName_string"); + } + + for (i = 0; ret == 0 && i < opt->policy_strings.num_strings; i++) { + char *oidstr, *uri, *dt; + + if ((oidstr = strdup(opt->policy_strings.strings[i])) == NULL) + hx509_err(context, 1, ENOMEM, "out of memory"); + uri = strchr(oidstr, ':'); + if (uri) + *(uri++) = '\0'; + dt = strchr(uri ? uri : "", ' '); + if (dt) + *(dt++) = '\0'; + + parse_oid(oidstr, NULL, &oid); + ret = hx509_ca_tbs_add_pol(context, tbs, &oid, uri, dt); + der_free_oid(&oid); + free(oidstr); + } + + for (i = 0; ret == 0 && i < opt->policy_mapping_strings.num_strings; i++) { + char *issuer_oidstr, *subject_oidstr; + heim_oid issuer_oid, subject_oid; + + if ((issuer_oidstr = + strdup(opt->policy_mapping_strings.strings[i])) == NULL) + hx509_err(context, 1, ENOMEM, "out of memory"); + subject_oidstr = strchr(issuer_oidstr, ':'); + if (subject_oidstr == NULL) + subject_oidstr = issuer_oidstr; + else + *(subject_oidstr++) = '\0'; + + parse_oid(issuer_oidstr, NULL, &issuer_oid); + parse_oid(subject_oidstr, NULL, &subject_oid); + ret = hx509_ca_tbs_add_pol_mapping(context, tbs, &issuer_oid, + &subject_oid); + if (ret) + hx509_err(context, 1, ret, "failed to add policy mapping"); + der_free_oid(&issuer_oid); + der_free_oid(&subject_oid); + free(issuer_oidstr); + } + + if (opt->issue_ca_flag) { + ret = hx509_ca_tbs_set_ca(context, tbs, opt->path_length_integer); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_set_ca"); + } + if (opt->issue_proxy_flag) { + ret = hx509_ca_tbs_set_proxy(context, tbs, opt->path_length_integer); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_set_proxy"); + } + if (opt->domain_controller_flag) { + hx509_ca_tbs_set_domaincontroller(context, tbs); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_set_domaincontroller"); + } + + if (delta) { + ret = hx509_ca_tbs_set_notAfter_lifetime(context, tbs, delta); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_set_notAfter_lifetime"); + } + if (opt->pkinit_max_life_string) { + time_t t = parse_time(opt->pkinit_max_life_string, "s"); + + ret = hx509_ca_tbs_set_pkinit_max_life(context, tbs, t); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_set_pkinit_max_life"); + } + + if (opt->self_signed_flag) { + ret = hx509_ca_sign_self(context, tbs, private_key, &cert); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_sign_self"); + } else { + ret = hx509_ca_sign(context, tbs, signer, &cert); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_sign"); + } + + if (cert_key) { + ret = _hx509_cert_assign_key(cert, cert_key); + if (ret) + hx509_err(context, 1, ret, "_hx509_cert_assign_key"); + } + + { + hx509_certs certs; + char *sn = fix_store_name(context, opt->certificate_string, "FILE"); + + ret = hx509_certs_init(context, sn, HX509_CERTS_CREATE, NULL, &certs); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_init"); + + ret = hx509_certs_add(context, certs, cert); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_add"); + + ret = hx509_certs_store(context, certs, 0, NULL); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_store"); + + hx509_certs_free(&certs); + free(sn); + } + + if (subject) + hx509_name_free(&subject); + if (signer) + hx509_cert_free(signer); + hx509_cert_free(cert); + free_SubjectPublicKeyInfo(&spki); + + if (private_key != cert_key) + hx509_private_key_free(&private_key); + hx509_private_key_free(&cert_key); + + hx509_ca_tbs_free(&tbs); + + return 0; +} + +static int HX509_LIB_CALL +test_one_cert(hx509_context hxcontext, void *ctx, hx509_cert cert) +{ + heim_octet_string sd, c; + hx509_verify_ctx vctx = ctx; + hx509_certs signer = NULL; + heim_oid type; + int ret; + + if (_hx509_cert_private_key(cert) == NULL) + return 0; + + ret = hx509_cms_create_signed_1(context, 0, NULL, NULL, 0, + NULL, cert, NULL, NULL, NULL, &sd); + if (ret) + errx(1, "hx509_cms_create_signed_1"); + + ret = hx509_cms_verify_signed(context, vctx, 0, sd.data, sd.length, + NULL, NULL, &type, &c, &signer); + free(sd.data); + if (ret) + hx509_err(context, 1, ret, "hx509_cms_verify_signed"); + + printf("create-signature verify-sigature done\n"); + + free(c.data); + + return 0; +} + +int +test_crypto(struct test_crypto_options *opt, int argc, char ** argv) +{ + hx509_verify_ctx vctx; + hx509_certs certs; + hx509_lock lock; + int i, ret; + + hx509_lock_init(context, &lock); + lock_strings(lock, &opt->pass_strings); + + ret = hx509_certs_init(context, "MEMORY:test-crypto", 0, NULL, &certs); + if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); + + for (i = 0; i < argc; i++) { + char *sn = fix_store_name(context, argv[i], "FILE"); + ret = hx509_certs_append(context, certs, lock, sn); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_append %s", sn); + free(sn); + } + + ret = hx509_verify_init_ctx(context, &vctx); + if (ret) + hx509_err(context, 1, ret, "hx509_verify_init_ctx"); + + hx509_verify_attach_anchors(vctx, certs); + + ret = hx509_certs_iter_f(context, certs, test_one_cert, vctx); + if (ret) + hx509_err(context, 1, ret, "hx509_cert_iter"); + + hx509_certs_free(&certs); + hx509_verify_destroy_ctx(vctx); + + return 0; +} + +int +statistic_print(struct statistic_print_options*opt, int argc, char **argv) +{ + int type = 0; + + if (stat_file_string == NULL) + errx(1, "no stat file"); + + if (opt->type_integer) + type = opt->type_integer; + + hx509_query_unparse_stats(context, type, stdout); + return 0; +} + +/* + * + */ + +int +crl_sign(struct crl_sign_options *opt, int argc, char **argv) +{ + hx509_crl crl; + heim_octet_string os; + hx509_cert signer = NULL; + hx509_lock lock; + int ret; + + hx509_lock_init(context, &lock); + lock_strings(lock, &opt->pass_strings); + + ret = hx509_crl_alloc(context, &crl); + if (ret) + errx(1, "crl alloc"); + + if (opt->signer_string == NULL) + errx(1, "signer missing"); + + { + hx509_certs certs = NULL; + hx509_query *q; + char *sn = fix_store_name(context, opt->signer_string, "FILE"); + + ret = hx509_certs_init(context, sn, 0, NULL, &certs); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_init: %s", sn); + + ret = hx509_query_alloc(context, &q); + if (ret) + hx509_err(context, 1, ret, "hx509_query_alloc: %d", ret); + + hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); + + ret = hx509_certs_find(context, certs, q, &signer); + hx509_query_free(context, q); + hx509_certs_free(&certs); + if (ret) + hx509_err(context, 1, ret, "no signer certificate found"); + free(sn); + } + + if (opt->lifetime_string) { + int delta; + + delta = parse_time(opt->lifetime_string, "day"); + if (delta < 0) + errx(1, "Invalid lifetime: %s", opt->lifetime_string); + + hx509_crl_lifetime(context, crl, delta); + } + + { + hx509_certs revoked = NULL; + int i; + + ret = hx509_certs_init(context, "MEMORY:revoked-certs", 0, + NULL, &revoked); + if (ret) + hx509_err(context, 1, ret, + "hx509_certs_init: MEMORY cert"); + + for (i = 0; i < argc; i++) { + char *sn = fix_store_name(context, argv[i], "FILE"); + + ret = hx509_certs_append(context, revoked, lock, sn); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_append: %s", sn); + free(sn); + } + + hx509_crl_add_revoked_certs(context, crl, revoked); + hx509_certs_free(&revoked); + } + + hx509_crl_sign(context, signer, crl, &os); + + if (opt->crl_file_string) + rk_dumpdata(opt->crl_file_string, os.data, os.length); + + free(os.data); + + hx509_crl_free(context, &crl); + hx509_cert_free(signer); + hx509_lock_free(lock); + + return 0; +} + +int +hxtool_list_oids(void *opt, int argc, char **argv) +{ + const heim_oid *oid; + int cursor = -1; + + while (der_match_heim_oid_by_name("", &cursor, &oid) == 0) { + char *s = NULL; + + if ((errno = der_print_heim_oid_sym(oid, '.', &s)) > 0) + err(1, "der_print_heim_oid_sym"); + printf("%s\n", s); + free(s); + } + return 0; +} + +static int +acert1_sans_utf8_other(struct acert_options *opt, + struct getarg_strings *wanted, + const char *type, + heim_any *san, + size_t *count) +{ + size_t k, len; + + if (!wanted->num_strings) + return 0; + for (k = 0; k < wanted->num_strings; k++) { + len = strlen(wanted->strings[k]); + if (len == san->length && + strncmp(san->data, wanted->strings[k], len) == 0) { + if (opt->verbose_flag) + fprintf(stderr, "Matched OtherName SAN %s (%s)\n", + wanted->strings[k], type); + (*count)++; + return 0; + } + } + if (opt->verbose_flag) + fprintf(stderr, "Did not match OtherName SAN %s (%s)\n", + wanted->strings[k], type); + return -1; +} + +static int +acert1_sans_other(struct acert_options *opt, + heim_oid *type_id, + heim_any *value, + size_t *count) +{ + heim_any pkinit; + size_t k, match; + const char *type_str = NULL; + char *s = NULL; + int ret; + + (void) der_print_heim_oid_sym(type_id, '.', &s); + type_str = s ? s : "<unknown>"; + if (der_heim_oid_cmp(type_id, &asn1_oid_id_pkix_on_xmppAddr) == 0) { + ret = acert1_sans_utf8_other(opt, &opt->has_xmpp_san_strings, + s ? s : "xmpp", value, count); + free(s); + return ret; + } + if (der_heim_oid_cmp(type_id, &asn1_oid_id_pkinit_san) != 0) { + if (opt->verbose_flag) + fprintf(stderr, "Ignoring OtherName SAN of type %s\n", type_str); + free(s); + return -1; + } + + free(s); + type_str = s = NULL; + + if (opt->has_pkinit_san_strings.num_strings == 0) + return 0; + + for (k = 0; k < opt->has_pkinit_san_strings.num_strings; k++) { + const char *s2 = opt->has_pkinit_san_strings.strings[k]; + + if ((ret = _hx509_make_pkinit_san(context, s2, &pkinit))) + return ret; + match = (pkinit.length == value->length && + memcmp(pkinit.data, value->data, pkinit.length) == 0); + free(pkinit.data); + if (match) { + if (opt->verbose_flag) + fprintf(stderr, "Matched PKINIT SAN %s\n", s2); + (*count)++; + return 0; + } + } + if (opt->verbose_flag) + fprintf(stderr, "Unexpected PKINIT SAN\n"); + return -1; +} + +static int +acert1_sans(struct acert_options *opt, + Extension *e, + size_t *count, + size_t *found) +{ + heim_printable_string hps; + GeneralNames gns; + size_t i, k, sz; + size_t unwanted = 0; + int ret = 0; + + memset(&gns, 0, sizeof(gns)); + decode_GeneralNames(e->extnValue.data, e->extnValue.length, &gns, &sz); + for (i = 0; (ret == -1 || ret == 0) && i < gns.len; i++) { + GeneralName *gn = &gns.val[i]; + const char *s; + + (*found)++; + if (gn->element == choice_GeneralName_rfc822Name) { + for (k = 0; k < opt->has_email_san_strings.num_strings; k++) { + s = opt->has_email_san_strings.strings[k]; + hps.data = rk_UNCONST(s); + hps.length = strlen(s); + if (der_printable_string_cmp(&gn->u.rfc822Name, &hps) == 0) { + if (opt->verbose_flag) + fprintf(stderr, "Matched e-mail address SAN %s\n", s); + (*count)++; + break; + } + } + if (k && k == opt->has_email_san_strings.num_strings) { + if (opt->verbose_flag) + fprintf(stderr, "Unexpected e-mail address SAN %.*s\n", + (int)gn->u.rfc822Name.length, + (const char *)gn->u.rfc822Name.data); + unwanted++; + } + } else if (gn->element == choice_GeneralName_dNSName) { + for (k = 0; k < opt->has_dnsname_san_strings.num_strings; k++) { + s = opt->has_dnsname_san_strings.strings[k]; + hps.data = rk_UNCONST(s); + hps.length = strlen(s); + if (der_printable_string_cmp(&gn->u.dNSName, &hps) == 0) { + if (opt->verbose_flag) + fprintf(stderr, "Matched dNSName SAN %s\n", s); + (*count)++; + break; + } + } + if (k && k == opt->has_dnsname_san_strings.num_strings) { + if (opt->verbose_flag) + fprintf(stderr, "Unexpected e-mail address SAN %.*s\n", + (int)gn->u.dNSName.length, + (const char *)gn->u.dNSName.data); + unwanted++; + } + } else if (gn->element == choice_GeneralName_registeredID) { + for (k = 0; k < opt->has_registeredID_san_strings.num_strings; k++) { + heim_oid oid; + + s = opt->has_registeredID_san_strings.strings[k]; + memset(&oid, 0, sizeof(oid)); + parse_oid(s, NULL, &oid); + if (der_heim_oid_cmp(&gn->u.registeredID, &oid) == 0) { + der_free_oid(&oid); + if (opt->verbose_flag) + fprintf(stderr, "Matched registeredID SAN %s\n", s); + (*count)++; + break; + } + der_free_oid(&oid); + } + if (k && k == opt->has_dnsname_san_strings.num_strings) { + if (opt->verbose_flag) + fprintf(stderr, "Unexpected registeredID SAN\n"); + unwanted++; + } + } else if (gn->element == choice_GeneralName_otherName) { + ret = acert1_sans_other(opt, &gn->u.otherName.type_id, + &gn->u.otherName.value, count); + } else if (opt->verbose_flag) { + fprintf(stderr, "Unexpected unsupported SAN\n"); + unwanted++; + } + } + free_GeneralNames(&gns); + if (ret == 0 && unwanted && opt->exact_flag) + return -1; + return ret; +} + +static int +acert1_ekus(struct acert_options *opt, + Extension *e, + size_t *count, + size_t *found) +{ + ExtKeyUsage eku; + size_t i, k, sz; + size_t unwanted = 0; + int ret = 0; + + memset(&eku, 0, sizeof(eku)); + decode_ExtKeyUsage(e->extnValue.data, e->extnValue.length, &eku, &sz); + for (i = 0; (ret == -1 || ret == 0) && i < eku.len; i++) { + (*found)++; + for (k = 0; k < opt->has_eku_strings.num_strings; k++) { + const char *s = opt->has_eku_strings.strings[k]; + heim_oid oid; + + memset(&oid, 0, sizeof(oid)); + parse_oid(s, NULL, &oid); + if (der_heim_oid_cmp(&eku.val[i], &oid) == 0) { + der_free_oid(&oid); + if (opt->verbose_flag) + fprintf(stderr, "Matched EKU OID %s\n", s); + (*count)++; + break; + } + der_free_oid(&oid); + } + if (k && k == opt->has_eku_strings.num_strings) { + char *oids = NULL; + + (void) der_print_heim_oid_sym(&eku.val[i], '.', &oids); + if (opt->verbose_flag) + fprintf(stderr, "Unexpected EKU OID %s\n", + oids ? oids : "<could-not-format-OID>"); + unwanted++; + } + } + free_ExtKeyUsage(&eku); + if (ret == 0 && unwanted && opt->exact_flag) + return -1; + return ret; +} + +static int +acert1_kus(struct acert_options *opt, + Extension *e, + size_t *count, + size_t *found) +{ + const struct units *u = asn1_KeyUsage_units(); + uint64_t ku_num; + KeyUsage ku; + size_t unwanted = 0; + size_t wanted = opt->has_ku_strings.num_strings; + size_t i, k, sz; + int ret; + + memset(&ku, 0, sizeof(ku)); + ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, &ku, &sz); + if (ret) + return ret; + ku_num = KeyUsage2int(ku); + + /* Validate requested key usage values */ + for (k = 0; k < wanted; k++) { + const char *s = opt->has_ku_strings.strings[k]; + + for (i = 0; u[i].name; i++) + if (strcmp(s, u[i].name) == 0) + break; + + if (u[i].name == NULL) + warnx("Warning: requested key usage %s unknown", s); + } + + for (i = 0; u[i].name; i++) { + if ((u[i].mult & ku_num)) + (*found)++; + for (k = 0; k < wanted; k++) { + const char *s = opt->has_ku_strings.strings[k]; + + if (!(u[i].mult & ku_num) || strcmp(s, u[i].name) != 0) + continue; + + if (opt->verbose_flag) + fprintf(stderr, "Matched key usage %s\n", s); + (*count)++; + break; + } + if ((u[i].mult & ku_num) && k == wanted) { + if (opt->verbose_flag) + fprintf(stderr, "Unexpected key usage %s\n", u[i].name); + unwanted++; + } + } + + return (unwanted && opt->exact_flag) ? -1 : 0; +} + +static time_t +ptime(const char *s) +{ + struct tm at_tm; + char *rest; + int at_s; + + if ((rest = strptime(s, "%Y-%m-%dT%H:%M:%S", &at_tm)) != NULL && + rest[0] == '\0') + return mktime(&at_tm); + if ((rest = strptime(s, "%Y%m%d%H%M%S", &at_tm)) != NULL && rest[0] == '\0') + return mktime(&at_tm); + if ((at_s = parse_time(s, "s")) != -1) + return time(NULL) + at_s; + errx(1, "Could not parse time spec %s", s); +} + +static int +acert1_validity(struct acert_options *opt, hx509_cert cert) +{ + time_t not_before_eq = 0; + time_t not_before_lt = 0; + time_t not_before_gt = 0; + time_t not_after_eq = 0; + time_t not_after_lt = 0; + time_t not_after_gt = 0; + int ret = 0; + + if (opt->valid_now_flag) { + time_t now = time(NULL); + + if (hx509_cert_get_notBefore(cert) > now) { + if (opt->verbose_flag) + fprintf(stderr, "Certificate not valid yet\n"); + ret = -1; + } + if (hx509_cert_get_notAfter(cert) < now) { + if (opt->verbose_flag) + fprintf(stderr, "Certificate currently expired\n"); + ret = -1; + } + } + if (opt->valid_at_string) { + time_t at = ptime(opt->valid_at_string); + + if (hx509_cert_get_notBefore(cert) > at) { + if (opt->verbose_flag) + fprintf(stderr, "Certificate not valid yet at %s\n", + opt->valid_at_string); + ret = -1; + } + if (hx509_cert_get_notAfter(cert) < at) { + if (opt->verbose_flag) + fprintf(stderr, "Certificate expired before %s\n", + opt->valid_at_string); + ret = -1; + } + } + + if (opt->not_before_eq_string) + not_before_eq = ptime(opt->not_before_eq_string); + if (opt->not_before_lt_string) + not_before_lt = ptime(opt->not_before_lt_string); + if (opt->not_before_gt_string) + not_before_gt = ptime(opt->not_before_gt_string); + if (opt->not_after_eq_string) + not_after_eq = ptime(opt->not_after_eq_string); + if (opt->not_after_lt_string) + not_after_lt = ptime(opt->not_after_lt_string); + if (opt->not_after_gt_string) + not_after_gt = ptime(opt->not_after_gt_string); + + if ((not_before_eq && hx509_cert_get_notBefore(cert) != not_before_eq) || + (not_before_lt && hx509_cert_get_notBefore(cert) >= not_before_lt) || + (not_before_gt && hx509_cert_get_notBefore(cert) <= not_before_gt)) { + if (opt->verbose_flag) + fprintf(stderr, "Certificate notBefore not as requested\n"); + ret = -1; + } + if ((not_after_eq && hx509_cert_get_notAfter(cert) != not_after_eq) || + (not_after_lt && hx509_cert_get_notAfter(cert) >= not_after_lt) || + (not_after_gt && hx509_cert_get_notAfter(cert) <= not_after_gt)) { + if (opt->verbose_flag) + fprintf(stderr, "Certificate notAfter not as requested\n"); + ret = -1; + } + + if (opt->has_private_key_flag && !hx509_cert_have_private_key(cert)) { + if (opt->verbose_flag) + fprintf(stderr, "Certificate does not have a private key\n"); + ret = -1; + } + + if (opt->lacks_private_key_flag && hx509_cert_have_private_key(cert)) { + if (opt->verbose_flag) + fprintf(stderr, "Certificate does not have a private key\n"); + ret = -1; + } + + return ret; +} + +static int +acert1(struct acert_options *opt, size_t cert_num, hx509_cert cert, int *matched) +{ + const heim_oid *misc_exts [] = { + &asn1_oid_id_x509_ce_authorityKeyIdentifier, + &asn1_oid_id_x509_ce_subjectKeyIdentifier, + &asn1_oid_id_x509_ce_basicConstraints, + &asn1_oid_id_x509_ce_nameConstraints, + &asn1_oid_id_x509_ce_certificatePolicies, + &asn1_oid_id_x509_ce_policyMappings, + &asn1_oid_id_x509_ce_issuerAltName, + &asn1_oid_id_x509_ce_subjectDirectoryAttributes, + &asn1_oid_id_x509_ce_policyConstraints, + &asn1_oid_id_x509_ce_cRLDistributionPoints, + &asn1_oid_id_x509_ce_deltaCRLIndicator, + &asn1_oid_id_x509_ce_issuingDistributionPoint, + &asn1_oid_id_x509_ce_inhibitAnyPolicy, + &asn1_oid_id_x509_ce_cRLNumber, + &asn1_oid_id_x509_ce_freshestCRL, + NULL + }; + const Certificate *c; + const Extensions *e; + KeyUsage ku; + size_t matched_elements = 0; + size_t wanted, sans_wanted, ekus_wanted, kus_wanted; + size_t found, sans_found, ekus_found, kus_found; + size_t i, k; + int ret; + + if ((c = _hx509_get_cert(cert)) == NULL) + errx(1, "Could not get Certificate"); + e = c->tbsCertificate.extensions; + + ret = _hx509_cert_get_keyusage(context, cert, &ku); + if (ret && ret != HX509_KU_CERT_MISSING) + hx509_err(context, 1, ret, "Could not get key usage of certificate"); + if (ret == HX509_KU_CERT_MISSING && opt->ca_flag) + return 0; /* want CA cert; this isn't it */ + if (ret == 0 && opt->ca_flag && !ku.keyCertSign) + return 0; /* want CA cert; this isn't it */ + if (ret == 0 && opt->end_entity_flag && ku.keyCertSign) + return 0; /* want EE cert; this isn't it */ + + if (opt->cert_num_integer != -1 && cert_num <= INT_MAX && + opt->cert_num_integer != (int)cert_num) + return 0; + if (opt->cert_num_integer == -1 || opt->cert_num_integer == (int)cert_num) + *matched = 1; + + if (_hx509_cert_get_version(c) < 3) { + warnx("Certificate with version %d < 3 ignored", + _hx509_cert_get_version(c)); + return 0; + } + + sans_wanted = opt->has_email_san_strings.num_strings + + opt->has_xmpp_san_strings.num_strings + + opt->has_ms_upn_san_strings.num_strings + + opt->has_dnsname_san_strings.num_strings + + opt->has_pkinit_san_strings.num_strings + + opt->has_registeredID_san_strings.num_strings; + ekus_wanted = opt->has_eku_strings.num_strings; + kus_wanted = opt->has_ku_strings.num_strings; + wanted = sans_wanted + ekus_wanted + kus_wanted; + sans_found = ekus_found = kus_found = 0; + + if (e == NULL) { + if (wanted) + return -1; + return acert1_validity(opt, cert); + } + + for (i = 0; i < e->len; i++) { + if (der_heim_oid_cmp(&e->val[i].extnID, + &asn1_oid_id_x509_ce_subjectAltName) == 0) { + ret = acert1_sans(opt, &e->val[i], &matched_elements, &sans_found); + if (ret == -1 && sans_wanted == 0 && + (!opt->exact_flag || sans_found == 0)) + ret = 0; + } else if (der_heim_oid_cmp(&e->val[i].extnID, + &asn1_oid_id_x509_ce_extKeyUsage) == 0) { + ret = acert1_ekus(opt, &e->val[i], &matched_elements, &ekus_found); + if (ret == -1 && ekus_wanted == 0 && + (!opt->exact_flag || ekus_found == 0)) + ret = 0; + } else if (der_heim_oid_cmp(&e->val[i].extnID, + &asn1_oid_id_x509_ce_keyUsage) == 0) { + ret = acert1_kus(opt, &e->val[i], &matched_elements, &kus_found); + if (ret == -1 && kus_wanted == 0 && + (!opt->exact_flag || kus_found == 0)) + ret = 0; + } else { + char *oids = NULL; + + for (k = 0; misc_exts[k]; k++) { + if (der_heim_oid_cmp(&e->val[i].extnID, misc_exts[k]) == 0) + break; + } + if (misc_exts[k]) + continue; + + (void) der_print_heim_oid(&e->val[i].extnID, '.', &oids); + warnx("Matching certificate has unexpected certificate " + "extension %s", oids ? oids : "<could not display OID>"); + free(oids); + ret = -1; + } + if (ret && ret != -1) + hx509_err(context, 1, ret, "Error checking matching certificate"); + if (ret == -1) + break; + } + if (matched_elements != wanted) + return -1; + found = sans_found + ekus_found + kus_found; + if (matched_elements != found && opt->exact_flag) + return -1; + if (ret) + return ret; + return acert1_validity(opt, cert); +} + +int +acert(struct acert_options *opt, int argc, char **argv) +{ + hx509_cursor cursor = NULL; + hx509_query *q = NULL; + hx509_certs certs = NULL; + hx509_cert cert = NULL; + char *sn = fix_store_name(context, argv[0], "FILE"); + size_t n = 0; + int matched = 0; + int ret; + + if (opt->not_after_eq_string && + (opt->not_after_lt_string || opt->not_after_gt_string)) + errx(1, "--not-after-eq should not be given with --not-after-lt/gt"); + if (opt->not_before_eq_string && + (opt->not_before_lt_string || opt->not_before_gt_string)) + errx(1, "--not-before-eq should not be given with --not-before-lt/gt"); + + if ((ret = hx509_certs_init(context, sn, 0, NULL, &certs))) + hx509_err(context, 1, ret, "Could not load certificates from %s", sn); + + if (opt->expr_string) { + if ((ret = hx509_query_alloc(context, &q)) || + (ret = hx509_query_match_expr(context, q, opt->expr_string))) + hx509_err(context, 1, ret, "Could not initialize query"); + if ((ret = hx509_certs_find(context, certs, q, &cert)) || !cert) + hx509_err(context, 1, ret, "No matching certificate"); + ret = acert1(opt, -1, cert, &matched); + matched = 1; + } else { + ret = hx509_certs_start_seq(context, certs, &cursor); + while (ret == 0 && + (ret = hx509_certs_next_cert(context, certs, + cursor, &cert)) == 0 && + cert) { + ret = acert1(opt, n++, cert, &matched); + if (matched) + break; + hx509_cert_free(cert); + cert = NULL; + } + if (cursor) + (void) hx509_certs_end_seq(context, certs, cursor); + } + if (!matched && ret) + hx509_err(context, 1, ret, "Could not find certificate"); + if (!matched) + errx(1, "Could not find certificate"); + if (ret == -1) + errx(1, "Matching certificate did not meet requirements"); + if (ret) + hx509_err(context, 1, ret, "Matching certificate did not meet " + "requirements"); + hx509_cert_free(cert); + free(sn); + return 0; +} + +/* + * + */ + +int +help(void *opt, int argc, char **argv) +{ + sl_slc_help(commands, argc, argv); + return 0; +} + +int +main(int argc, char **argv) +{ + int ret, optidx = 0; + + setprogname (argv[0]); + + if(getarg(args, num_args, argc, argv, &optidx)) + usage(1); + if(help_flag) + usage(0); + if(version_flag) { + print_version(NULL); + exit(0); + } + argv += optidx; + argc -= optidx; + + if (argc == 0) + usage(1); + + ret = hx509_context_init(&context); + if (ret) + errx(1, "hx509_context_init failed with %d", ret); + + if (stat_file_string) + hx509_query_statistic_file(context, stat_file_string); + + ret = sl_command(commands, argc, argv); + if(ret == -1) + warnx ("unrecognized command: %s", argv[0]); + + hx509_context_free(&context); + + return ret; +} diff --git a/third_party/heimdal/lib/hx509/keyset.c b/third_party/heimdal/lib/hx509/keyset.c new file mode 100644 index 0000000..f25cdf4 --- /dev/null +++ b/third_party/heimdal/lib/hx509/keyset.c @@ -0,0 +1,846 @@ +/* + * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" + +/** + * @page page_keyset Certificate store operations + * + * Type of certificates store: + * - MEMORY + * In memory based format. Doesn't support storing. + * - FILE + * FILE supports raw DER certicates and PEM certicates. When PEM is + * used the file can contain may certificates and match private + * keys. Support storing the certificates. DER format only supports + * on certificate and no private key. + * - PEM-FILE + * Same as FILE, defaulting to PEM encoded certificates. + * - PEM-FILE + * Same as FILE, defaulting to DER encoded certificates. + * - PKCS11 + * - PKCS12 + * - DIR + * - KEYCHAIN + * Apple Mac OS X KeyChain backed keychain object. + * + * See the library functions here: @ref hx509_keyset + */ + +struct hx509_certs_data { + unsigned int ref; + struct hx509_keyset_ops *ops; + void *ops_data; + int flags; +}; + +struct hx509_keyset_ops * +_hx509_ks_type(hx509_context context, const char *type) +{ + int i; + + for (i = 0; i < context->ks_num_ops; i++) + if (strcasecmp(type, context->ks_ops[i]->name) == 0) + return context->ks_ops[i]; + + return NULL; +} + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_ks_register(hx509_context context, struct hx509_keyset_ops *ops) +{ + struct hx509_keyset_ops **val; + + if (_hx509_ks_type(context, ops->name)) + return; + + val = realloc(context->ks_ops, + (context->ks_num_ops + 1) * sizeof(context->ks_ops[0])); + if (val == NULL) + return; + val[context->ks_num_ops] = ops; + context->ks_ops = val; + context->ks_num_ops++; +} + +/** + * Open or creates a new hx509 certificate store. + * + * @param context A hx509 context + * @param name name of the store, format is TYPE:type-specific-string, + * if NULL is used the MEMORY store is used. + * @param flags list of flags: + * - HX509_CERTS_CREATE create a new keystore of the specific TYPE. + * - HX509_CERTS_UNPROTECT_ALL fails if any private key failed to be extracted. + * - HX509_CERTS_NO_PRIVATE_KEYS does not load or permit adding private keys + * @param lock a lock that unlocks the certificates store, use NULL to + * select no password/certifictes/prompt lock (see @ref page_lock). + * @param certs return pointer, free with hx509_certs_free(). + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_certs_init(hx509_context context, + const char *name, int flags, + hx509_lock lock, hx509_certs *certs) +{ + struct hx509_keyset_ops *ops; + const char *residue; + hx509_certs c; + char *type; + int ret; + + *certs = NULL; + + if (name == NULL) + name = ""; + + residue = strchr(name, ':'); + if (residue) { + type = malloc(residue - name + 1); + if (type) + strlcpy(type, name, residue - name + 1); + residue++; + if (residue[0] == '\0') + residue = NULL; + } else { + type = strdup("MEMORY"); + residue = name; + } + if (type == NULL) { + hx509_clear_error_string(context); + return ENOMEM; + } + + ops = _hx509_ks_type(context, type); + if (ops == NULL) { + hx509_set_error_string(context, 0, ENOENT, + "Keyset type %s is not supported", type); + free(type); + return ENOENT; + } + free(type); + c = calloc(1, sizeof(*c)); + if (c == NULL) { + hx509_clear_error_string(context); + return ENOMEM; + } + c->flags = flags; + c->ops = ops; + c->ref = 1; + + ret = (*ops->init)(context, c, &c->ops_data, flags, residue, lock); + if (ret) { + free(c); + return ret; + } + + *certs = c; + return 0; +} + +/** + * Destroys and frees a hx509 certificate store. + * + * @param context A hx509 context + * @param certs A store to destroy + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_certs_destroy(hx509_context context, + hx509_certs *certs) +{ + int ret = 0; + + if (*certs) { + if ((*certs)->ops->destroy) + ret = ((*certs)->ops->destroy)(context, *certs, (*certs)->ops_data); + else + ret = ENOTSUP; + } + hx509_certs_free(certs); + return ret; +} + +/** + * Write the certificate store to stable storage. + * + * Use the HX509_CERTS_STORE_NO_PRIVATE_KEYS flag to ensure that no private + * keys are stored, even if added. + * + * @param context A hx509 context. + * @param certs a certificate store to store. + * @param flags currently one flag is defined: HX509_CERTS_STORE_NO_PRIVATE_KEYS + * @param lock a lock that unlocks the certificates store, use NULL to + * select no password/certifictes/prompt lock (see @ref page_lock). + * + * @return Returns an hx509 error code. HX509_UNSUPPORTED_OPERATION if + * the certificate store doesn't support the store operation. + * + * @ingroup hx509_keyset + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_certs_store(hx509_context context, + hx509_certs certs, + int flags, + hx509_lock lock) +{ + if (certs->ops->store == NULL) { + hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION, + "keystore if type %s doesn't support " + "store operation", + certs->ops->name); + return HX509_UNSUPPORTED_OPERATION; + } + + return (*certs->ops->store)(context, certs, certs->ops_data, flags, lock); +} + + +HX509_LIB_FUNCTION hx509_certs HX509_LIB_CALL +hx509_certs_ref(hx509_certs certs) +{ + if (certs == NULL) + return NULL; + if (certs->ref == 0) + _hx509_abort("certs refcount == 0 on ref"); + if (certs->ref == UINT_MAX) + _hx509_abort("certs refcount == UINT_MAX on ref"); + certs->ref++; + return certs; +} + +/** + * Free a certificate store. + * + * @param certs certificate store to free. + * + * @ingroup hx509_keyset + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_certs_free(hx509_certs *certs) +{ + if (*certs) { + if ((*certs)->ref == 0) + _hx509_abort("cert refcount == 0 on free"); + if (--(*certs)->ref > 0) + return; + + (*(*certs)->ops->free)(*certs, (*certs)->ops_data); + free(*certs); + *certs = NULL; + } +} + +/** + * Start the integration + * + * @param context a hx509 context. + * @param certs certificate store to iterate over + * @param cursor cursor that will keep track of progress, free with + * hx509_certs_end_seq(). + * + * @return Returns an hx509 error code. HX509_UNSUPPORTED_OPERATION is + * returned if the certificate store doesn't support the iteration + * operation. + * + * @ingroup hx509_keyset + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_certs_start_seq(hx509_context context, + hx509_certs certs, + hx509_cursor *cursor) +{ + int ret; + + if (certs->ops->iter_start == NULL) { + hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION, + "Keyset type %s doesn't support iteration", + certs->ops->name); + return HX509_UNSUPPORTED_OPERATION; + } + + ret = (*certs->ops->iter_start)(context, certs, certs->ops_data, cursor); + if (ret) + return ret; + + return 0; +} + +/** + * Get next ceritificate from the certificate keystore pointed out by + * cursor. + * + * @param context a hx509 context. + * @param certs certificate store to iterate over. + * @param cursor cursor that keeps track of progress. + * @param cert return certificate next in store, NULL if the store + * contains no more certificates. Free with hx509_cert_free(). + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_certs_next_cert(hx509_context context, + hx509_certs certs, + hx509_cursor cursor, + hx509_cert *cert) +{ + *cert = NULL; + return (*certs->ops->iter)(context, certs, certs->ops_data, cursor, cert); +} + +/** + * End the iteration over certificates. + * + * @param context a hx509 context. + * @param certs certificate store to iterate over. + * @param cursor cursor that will keep track of progress, freed. + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_certs_end_seq(hx509_context context, + hx509_certs certs, + hx509_cursor cursor) +{ + (*certs->ops->iter_end)(context, certs, certs->ops_data, cursor); + return 0; +} + +/** + * Iterate over all certificates in a keystore and call a function + * for each of them. + * + * @param context a hx509 context. + * @param certs certificate store to iterate over. + * @param func function to call for each certificate. The function + * should return non-zero to abort the iteration, that value is passed + * back to the caller of hx509_certs_iter_f(). + * @param ctx context variable that will passed to the function. + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_certs_iter_f(hx509_context context, + hx509_certs certs, + int (HX509_LIB_CALL *func)(hx509_context, void *, hx509_cert), + void *ctx) +{ + hx509_cursor cursor; + hx509_cert c; + int ret; + + ret = hx509_certs_start_seq(context, certs, &cursor); + if (ret) + return ret; + + while (1) { + ret = hx509_certs_next_cert(context, certs, cursor, &c); + if (ret) + break; + if (c == NULL) { + ret = 0; + break; + } + ret = (*func)(context, ctx, c); + hx509_cert_free(c); + if (ret) + break; + } + + hx509_certs_end_seq(context, certs, cursor); + + return ret; +} + +#ifdef __BLOCKS__ + +static int +certs_iter(hx509_context context, void *ctx, hx509_cert cert) +{ + int (^func)(hx509_cert) = ctx; + return func(cert); +} + +/** + * Iterate over all certificates in a keystore and call a block + * for each of them. + * + * @param context a hx509 context. + * @param certs certificate store to iterate over. + * @param func block to call for each certificate. The function + * should return non-zero to abort the iteration, that value is passed + * back to the caller of hx509_certs_iter(). + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_certs_iter(hx509_context context, + hx509_certs certs, + int (^func)(hx509_cert)) +{ + return hx509_certs_iter_f(context, certs, certs_iter, func); +} +#endif + + +/** + * Function to use to hx509_certs_iter_f() as a function argument, the + * ctx variable to hx509_certs_iter_f() should be a FILE file descriptor. + * + * @param context a hx509 context. + * @param ctx used by hx509_certs_iter_f(). + * @param c a certificate + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ci_print_names(hx509_context context, void *ctx, hx509_cert c) +{ + Certificate *cert; + hx509_name n; + char *s, *i; + + cert = _hx509_get_cert(c); + + _hx509_name_from_Name(&cert->tbsCertificate.subject, &n); + hx509_name_to_string(n, &s); + hx509_name_free(&n); + _hx509_name_from_Name(&cert->tbsCertificate.issuer, &n); + hx509_name_to_string(n, &i); + hx509_name_free(&n); + fprintf(ctx, "subject: %s\nissuer: %s\n", s, i); + free(s); + free(i); + return 0; +} + +/** + * Add a certificate to the certificiate store. + * + * The receiving keyset certs will either increase reference counter + * of the cert or make a deep copy, either way, the caller needs to + * free the cert itself. + * + * @param context a hx509 context. + * @param certs certificate store to add the certificate to. + * @param cert certificate to add. + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_certs_add(hx509_context context, hx509_certs certs, hx509_cert cert) +{ + hx509_cert copy = NULL; + int ret; + + if (certs->ops->add == NULL) { + hx509_set_error_string(context, 0, ENOENT, + "Keyset type %s doesn't support add operation", + certs->ops->name); + return ENOENT; + } + + if ((certs->flags & HX509_CERTS_NO_PRIVATE_KEYS) && + hx509_cert_have_private_key(cert)) { + if ((copy = hx509_cert_copy_no_private_key(context, cert, + NULL)) == NULL) { + hx509_set_error_string(context, 0, ENOMEM, + "Could not add certificate to store"); + return ENOMEM; + } + cert = copy; + } + + ret = (*certs->ops->add)(context, certs, certs->ops_data, cert); + hx509_cert_free(copy); + return ret; +} + +/** + * Find a certificate matching the query. + * + * @param context a hx509 context. + * @param certs certificate store to search. + * @param q query allocated with @ref hx509_query functions. + * @param r return certificate (or NULL on error), should be freed + * with hx509_cert_free(). + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_certs_find(hx509_context context, + hx509_certs certs, + const hx509_query *q, + hx509_cert *r) +{ + hx509_cursor cursor; + hx509_cert c; + int ret; + + *r = NULL; + + _hx509_query_statistic(context, 0, q); + + if (certs->ops->query) + return (*certs->ops->query)(context, certs, certs->ops_data, q, r); + + ret = hx509_certs_start_seq(context, certs, &cursor); + if (ret) + return ret; + + c = NULL; + while (1) { + ret = hx509_certs_next_cert(context, certs, cursor, &c); + if (ret) + break; + if (c == NULL) + break; + if (_hx509_query_match_cert(context, q, c)) { + *r = c; + c = NULL; + break; + } + hx509_cert_free(c); + c = NULL; + } + + hx509_cert_free(c); + hx509_certs_end_seq(context, certs, cursor); + if (ret) + return ret; + /** + * Return HX509_CERT_NOT_FOUND if no certificate in certs matched + * the query. + */ + if (*r == NULL) { + hx509_clear_error_string(context); + return HX509_CERT_NOT_FOUND; + } + + return 0; +} + +/** + * Filter certificate matching the query. + * + * @param context a hx509 context. + * @param certs certificate store to search. + * @param q query allocated with @ref hx509_query functions. + * @param result the filtered certificate store, caller must free with + * hx509_certs_free(). + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_certs_filter(hx509_context context, + hx509_certs certs, + const hx509_query *q, + hx509_certs *result) +{ + hx509_cursor cursor; + hx509_cert c; + int ret, found = 0; + + _hx509_query_statistic(context, 0, q); + + ret = hx509_certs_init(context, "MEMORY:filter-certs", 0, + NULL, result); + if (ret) + return ret; + + ret = hx509_certs_start_seq(context, certs, &cursor); + if (ret) { + hx509_certs_free(result); + return ret; + } + + c = NULL; + while (1) { + ret = hx509_certs_next_cert(context, certs, cursor, &c); + if (ret) + break; + if (c == NULL) + break; + if (_hx509_query_match_cert(context, q, c)) { + hx509_certs_add(context, *result, c); + found = 1; + } + hx509_cert_free(c); + } + + hx509_certs_end_seq(context, certs, cursor); + if (ret) { + hx509_certs_free(result); + return ret; + } + + /** + * Return HX509_CERT_NOT_FOUND if no certificate in certs matched + * the query. + */ + if (!found) { + hx509_certs_free(result); + hx509_clear_error_string(context); + return HX509_CERT_NOT_FOUND; + } + + return 0; +} + + +static int HX509_LIB_CALL +certs_merge_func(hx509_context context, void *ctx, hx509_cert c) +{ + return hx509_certs_add(context, (hx509_certs)ctx, c); +} + +/** + * Merge one certificate store into another. The from store is kept intact. + * + * @param context a hx509 context. + * @param to the store to merge into. + * @param from the store to copy the object from. + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_certs_merge(hx509_context context, hx509_certs to, hx509_certs from) +{ + if (from == NULL) + return 0; + return hx509_certs_iter_f(context, from, certs_merge_func, to); +} + +/** + * Same a hx509_certs_merge() but use a lock and name to describe the + * from source. + * + * @param context a hx509 context. + * @param to the store to merge into. + * @param lock a lock that unlocks the certificates store, use NULL to + * select no password/certifictes/prompt lock (see @ref page_lock). + * @param name name of the source store + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_certs_append(hx509_context context, + hx509_certs to, + hx509_lock lock, + const char *name) +{ + hx509_certs s; + int ret; + + ret = hx509_certs_init(context, name, 0, lock, &s); + if (ret) + return ret; + ret = hx509_certs_merge(context, to, s); + hx509_certs_free(&s); + return ret; +} + +/** + * Get one random certificate from the certificate store. + * + * @param context a hx509 context. + * @param certs a certificate store to get the certificate from. + * @param c return certificate, should be freed with hx509_cert_free(). + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_get_one_cert(hx509_context context, hx509_certs certs, hx509_cert *c) +{ + hx509_cursor cursor; + int ret; + + *c = NULL; + + ret = hx509_certs_start_seq(context, certs, &cursor); + if (ret) + return ret; + + ret = hx509_certs_next_cert(context, certs, cursor, c); + if (ret) + return ret; + + hx509_certs_end_seq(context, certs, cursor); + return 0; +} + +static int +certs_info_stdio(void *ctx, const char *str) +{ + FILE *f = ctx; + fprintf(f, "%s\n", str); + return 0; +} + +/** + * Print some info about the certificate store. + * + * @param context a hx509 context. + * @param certs certificate store to print information about. + * @param func function that will get each line of the information, if + * NULL is used the data is printed on a FILE descriptor that should + * be passed in ctx, if ctx also is NULL, stdout is used. + * @param ctx parameter to func. + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_certs_info(hx509_context context, + hx509_certs certs, + int (*func)(void *, const char *), + void *ctx) +{ + if (func == NULL) { + func = certs_info_stdio; + if (ctx == NULL) + ctx = stdout; + } + if (certs->ops->printinfo == NULL) { + (*func)(ctx, "No info function for certs"); + return 0; + } + return (*certs->ops->printinfo)(context, certs, certs->ops_data, + func, ctx); +} + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_pi_printf(int (*func)(void *, const char *), void *ctx, + const char *fmt, ...) +{ + va_list ap; + char *str; + int ret; + + va_start(ap, fmt); + ret = vasprintf(&str, fmt, ap); + va_end(ap); + if (ret == -1 || str == NULL) + return; + (*func)(ctx, str); + free(str); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_certs_keys_get(hx509_context context, + hx509_certs certs, + hx509_private_key **keys) +{ + if (certs->ops->getkeys == NULL) { + *keys = NULL; + return 0; + } + return (*certs->ops->getkeys)(context, certs, certs->ops_data, keys); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_certs_keys_add(hx509_context context, + hx509_certs certs, + hx509_private_key key) +{ + if (certs->ops->addkey == NULL) { + hx509_set_error_string(context, 0, EINVAL, + "keystore if type %s doesn't support " + "key add operation", + certs->ops->name); + return EINVAL; + } + return (*certs->ops->addkey)(context, certs, certs->ops_data, key); +} + + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_certs_keys_free(hx509_context context, + hx509_private_key *keys) +{ + size_t i; + + if (keys == NULL) + return; + for (i = 0; keys[i]; i++) + hx509_private_key_free(&keys[i]); + free(keys); +} diff --git a/third_party/heimdal/lib/hx509/ks_dir.c b/third_party/heimdal/lib/hx509/ks_dir.c new file mode 100644 index 0000000..3bc99f2 --- /dev/null +++ b/third_party/heimdal/lib/hx509/ks_dir.c @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" +#include <dirent.h> + +/* + * The DIR keyset module is strange compared to the other modules + * since it does lazy evaluation and really doesn't keep any local + * state except for the directory iteration and cert iteration of + * files. DIR ignores most errors so that the consumer doesn't get + * failes for stray files in directories. + */ + +struct dircursor { + DIR *dir; + hx509_certs certs; + void *iter; +}; + +/* + * + */ + +static int +dir_init(hx509_context context, + hx509_certs certs, void **data, int flags, + const char *residue, hx509_lock lock) +{ + *data = NULL; + + if (residue == NULL || residue[0] == '\0') { + hx509_set_error_string(context, 0, EINVAL, + "DIR file name not specified"); + return EINVAL; + } + + { + struct stat sb; + int ret; + + ret = stat(residue, &sb); + if (ret == -1) { + hx509_set_error_string(context, 0, ENOENT, + "No such file %s", residue); + return ENOENT; + } + + if (!S_ISDIR(sb.st_mode)) { + hx509_set_error_string(context, 0, ENOTDIR, + "%s is not a directory", residue); + return ENOTDIR; + } + } + + *data = strdup(residue); + if (*data == NULL) { + hx509_clear_error_string(context); + return ENOMEM; + } + + return 0; +} + +static int +dir_free(hx509_certs certs, void *data) +{ + free(data); + return 0; +} + +static int +dir_iter_start(hx509_context context, + hx509_certs certs, void *data, void **cursor) +{ + struct dircursor *d; + + *cursor = NULL; + + d = calloc(1, sizeof(*d)); + if (d == NULL) { + hx509_clear_error_string(context); + return ENOMEM; + } + + d->dir = opendir(data); + if (d->dir == NULL) { + hx509_clear_error_string(context); + free(d); + return errno; + } + rk_cloexec_dir(d->dir); + d->certs = NULL; + d->iter = NULL; + + *cursor = d; + return 0; +} + +static int +dir_iter(hx509_context context, + hx509_certs certs, void *data, void *iter, hx509_cert *cert) +{ + struct dircursor *d = iter; + int ret = 0; + + *cert = NULL; + + do { + struct dirent *dir; + char *fn; + + if (d->certs) { + ret = hx509_certs_next_cert(context, d->certs, d->iter, cert); + if (ret) { + hx509_certs_end_seq(context, d->certs, d->iter); + d->iter = NULL; + hx509_certs_free(&d->certs); + return ret; + } + if (*cert) { + ret = 0; + break; + } + hx509_certs_end_seq(context, d->certs, d->iter); + d->iter = NULL; + hx509_certs_free(&d->certs); + } + + dir = readdir(d->dir); + if (dir == NULL) { + ret = 0; + break; + } + if (strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0) + continue; + + if (asprintf(&fn, "FILE:%s/%s", (char *)data, dir->d_name) == -1) + return ENOMEM; + + ret = hx509_certs_init(context, fn, 0, NULL, &d->certs); + if (ret == 0) { + + ret = hx509_certs_start_seq(context, d->certs, &d->iter); + if (ret) + hx509_certs_free(&d->certs); + } + /* ignore errors */ + if (ret) { + d->certs = NULL; + ret = 0; + } + + free(fn); + } while(ret == 0); + + return ret; +} + + +static int +dir_iter_end(hx509_context context, + hx509_certs certs, + void *data, + void *cursor) +{ + struct dircursor *d = cursor; + + if (d->certs) { + hx509_certs_end_seq(context, d->certs, d->iter); + d->iter = NULL; + hx509_certs_free(&d->certs); + } + closedir(d->dir); + free(d); + return 0; +} + + +static struct hx509_keyset_ops keyset_dir = { + "DIR", + 0, + dir_init, + NULL, + dir_free, + NULL, + NULL, + dir_iter_start, + dir_iter, + dir_iter_end, + NULL, + NULL, + NULL, + NULL +}; + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_ks_dir_register(hx509_context context) +{ + _hx509_ks_register(context, &keyset_dir); +} diff --git a/third_party/heimdal/lib/hx509/ks_file.c b/third_party/heimdal/lib/hx509/ks_file.c new file mode 100644 index 0000000..880668b --- /dev/null +++ b/third_party/heimdal/lib/hx509/ks_file.c @@ -0,0 +1,800 @@ +/* + * Copyright (c) 2005 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" +#ifndef WIN32 +#include <libgen.h> +#endif + +typedef enum { USE_PEM, USE_DER } outformat; + +struct ks_file { + hx509_certs certs; + char *fn; + outformat format; +}; + +/* + * + */ + +static int +parse_certificate(hx509_context context, const char *fn, int flags, + struct hx509_collector *c, + const hx509_pem_header *headers, + const void *data, size_t len, + const AlgorithmIdentifier *ai) +{ + heim_error_t error = NULL; + hx509_cert cert; + int ret; + + cert = hx509_cert_init_data(context, data, len, &error); + if (cert == NULL) { + ret = heim_error_get_code(error); + heim_release(error); + return ret; + } + + ret = _hx509_collector_certs_add(context, c, cert); + hx509_cert_free(cert); + return ret; +} + +static int +try_decrypt(hx509_context context, + struct hx509_collector *collector, + int flags, + const AlgorithmIdentifier *alg, + const EVP_CIPHER *c, + const void *ivdata, + const void *password, + size_t passwordlen, + const void *cipher, + size_t len) +{ + heim_octet_string clear; + size_t keylen; + void *key; + int ret; + + keylen = EVP_CIPHER_key_length(c); + + key = malloc(keylen); + if (key == NULL) { + hx509_clear_error_string(context); + return ENOMEM; + } + + ret = EVP_BytesToKey(c, EVP_md5(), ivdata, + password, passwordlen, + 1, key, NULL); + if (ret <= 0) { + ret = HX509_CRYPTO_INTERNAL_ERROR; + hx509_set_error_string(context, 0, ret, + "Failed to do string2key for private key"); + goto out; + } + + clear.data = malloc(len); + if (clear.data == NULL) { + hx509_set_error_string(context, 0, ENOMEM, + "Out of memory to decrypt for private key"); + ret = ENOMEM; + goto out; + } + clear.length = len; + + { + EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX_init(&ctx); + EVP_CipherInit_ex(&ctx, c, NULL, key, ivdata, 0); + EVP_Cipher(&ctx, clear.data, cipher, len); + EVP_CIPHER_CTX_cleanup(&ctx); + } + + if (!(flags & HX509_CERTS_NO_PRIVATE_KEYS)) + ret = _hx509_collector_private_key_add(context, collector, alg, NULL, + &clear, NULL); + + memset_s(clear.data, clear.length, 0, clear.length); + free(clear.data); +out: + memset_s(key, keylen, 0, keylen); + free(key); + return ret; +} + +static int +parse_pkcs8_private_key(hx509_context context, const char *fn, int flags, + struct hx509_collector *c, + const hx509_pem_header *headers, + const void *data, size_t length, + const AlgorithmIdentifier *ai) +{ + PKCS8PrivateKeyInfo ki; + heim_octet_string keydata; + int ret; + + ret = decode_PKCS8PrivateKeyInfo(data, length, &ki, NULL); + if (ret) + return ret; + + if (!(flags & HX509_CERTS_NO_PRIVATE_KEYS)) { + keydata.data = rk_UNCONST(data); + keydata.length = length; + ret = _hx509_collector_private_key_add(context, + c, + &ki.privateKeyAlgorithm, + NULL, + &ki.privateKey, + &keydata); + } + free_PKCS8PrivateKeyInfo(&ki); + return ret; +} + +static int +parse_pem_private_key(hx509_context context, const char *fn, int flags, + struct hx509_collector *c, + const hx509_pem_header *headers, + const void *data, size_t len, + const AlgorithmIdentifier *ai) +{ + int ret = 0; + const char *enc; + + enc = hx509_pem_find_header(headers, "Proc-Type"); + if (enc) { + const char *dek; + char *type, *iv; + ssize_t ssize, size; + void *ivdata; + const EVP_CIPHER *cipher; + const struct _hx509_password *pw; + hx509_lock lock; + int decrypted = 0; + size_t i; + + lock = _hx509_collector_get_lock(c); + if (lock == NULL) { + hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP, + "Failed to get password for " + "password protected file %s", fn); + return HX509_ALG_NOT_SUPP; + } + + if (strcmp(enc, "4,ENCRYPTED") != 0) { + hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, + "Private key encrypted in unknown method %s " + "in file", + enc, fn); + hx509_clear_error_string(context); + return HX509_PARSING_KEY_FAILED; + } + + dek = hx509_pem_find_header(headers, "DEK-Info"); + if (dek == NULL) { + hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, + "Encrypted private key missing DEK-Info"); + return HX509_PARSING_KEY_FAILED; + } + + type = strdup(dek); + if (type == NULL) { + hx509_clear_error_string(context); + return ENOMEM; + } + + iv = strchr(type, ','); + if (iv == NULL) { + free(type); + hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, + "IV missing"); + return HX509_PARSING_KEY_FAILED; + } + + *iv++ = '\0'; + + size = strlen(iv); + ivdata = malloc(size); + if (ivdata == NULL) { + hx509_clear_error_string(context); + free(type); + return ENOMEM; + } + + cipher = EVP_get_cipherbyname(type); + if (cipher == NULL) { + free(ivdata); + hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP, + "Private key encrypted with " + "unsupported cipher: %s", + type); + free(type); + return HX509_ALG_NOT_SUPP; + } + +#define PKCS5_SALT_LEN 8 + + ssize = hex_decode(iv, ivdata, size); + free(type); + type = NULL; + iv = NULL; + + if (ssize < 0 || ssize < PKCS5_SALT_LEN || ssize < EVP_CIPHER_iv_length(cipher)) { + free(ivdata); + hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, + "Salt have wrong length in " + "private key file"); + return HX509_PARSING_KEY_FAILED; + } + + pw = _hx509_lock_get_passwords(lock); + if (pw != NULL) { + const void *password; + size_t passwordlen; + + for (i = 0; i < pw->len; i++) { + password = pw->val[i]; + passwordlen = strlen(password); + + ret = try_decrypt(context, c, flags, ai, cipher, ivdata, + password, passwordlen, data, len); + if (ret == 0) { + decrypted = 1; + break; + } + } + } + if (!decrypted) { + hx509_prompt prompt; + char password[128]; + + memset(&prompt, 0, sizeof(prompt)); + + prompt.prompt = "Password for keyfile: "; + prompt.type = HX509_PROMPT_TYPE_PASSWORD; + prompt.reply.data = password; + prompt.reply.length = sizeof(password); + + ret = hx509_lock_prompt(lock, &prompt); + if (ret == 0) + ret = try_decrypt(context, c, flags, ai, cipher, ivdata, + password, strlen(password), data, len); + /* XXX add password to lock password collection ? */ + memset_s(password, sizeof(password), 0, sizeof(password)); + } + free(ivdata); + + } else if (!(flags & HX509_CERTS_NO_PRIVATE_KEYS)) { + heim_octet_string keydata; + + keydata.data = rk_UNCONST(data); + keydata.length = len; + + ret = _hx509_collector_private_key_add(context, c, ai, NULL, + &keydata, NULL); + } + + return ret; +} + + +struct pem_formats { + const char *name; + int (*func)(hx509_context, const char *, int, struct hx509_collector *, + const hx509_pem_header *, const void *, size_t, + const AlgorithmIdentifier *); + const AlgorithmIdentifier *(*ai)(void); +} formats[] = { + { "CERTIFICATE", parse_certificate, NULL }, + { "PRIVATE KEY", parse_pkcs8_private_key, NULL }, + { "RSA PRIVATE KEY", parse_pem_private_key, hx509_signature_rsa }, +#ifdef HAVE_HCRYPTO_W_OPENSSL + { "EC PRIVATE KEY", parse_pem_private_key, hx509_signature_ecPublicKey } +#endif +}; + + +struct pem_ctx { + int flags; + struct hx509_collector *c; +}; + +static int +pem_func(hx509_context context, const char *type, + const hx509_pem_header *header, + const void *data, size_t len, void *ctx) +{ + struct pem_ctx *pem_ctx = (struct pem_ctx*)ctx; + int ret = 0; + size_t j; + + for (j = 0; j < sizeof(formats)/sizeof(formats[0]); j++) { + const char *q = formats[j].name; + if (strcasecmp(type, q) == 0) { + const AlgorithmIdentifier *ai = NULL; + + if (formats[j].ai != NULL) + ai = (*formats[j].ai)(); + + ret = (*formats[j].func)(context, NULL, pem_ctx->flags, pem_ctx->c, + header, data, len, ai); + if (ret && (pem_ctx->flags & HX509_CERTS_UNPROTECT_ALL)) { + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + "Failed parseing PEM format %s", type); + return ret; + } + break; + } + } + if (j == sizeof(formats)/sizeof(formats[0])) { + ret = HX509_UNSUPPORTED_OPERATION; + hx509_set_error_string(context, 0, ret, + "Found no matching PEM format for %s", type); + return ret; + } + return 0; +} + +/* + * + */ + +static int +file_init_common(hx509_context context, + hx509_certs certs, void **data, int flags, + const char *residue, hx509_lock lock, outformat format) +{ + char *p, *pnext; + struct ks_file *ksf = NULL; + hx509_private_key *keys = NULL; + int ret; + struct pem_ctx pem_ctx; + + pem_ctx.flags = flags; + pem_ctx.c = NULL; + + if (residue == NULL || residue[0] == '\0') { + hx509_set_error_string(context, 0, EINVAL, + "PEM file name not specified"); + return EINVAL; + } + + *data = NULL; + + if (lock == NULL) + lock = _hx509_empty_lock; + + ksf = calloc(1, sizeof(*ksf)); + if (ksf == NULL) { + hx509_clear_error_string(context); + return ENOMEM; + } + ksf->format = format; + + ksf->fn = strdup(residue); + if (ksf->fn == NULL) { + hx509_clear_error_string(context); + ret = ENOMEM; + goto out; + } + + /* + * XXX this is broken, the function should parse the file before + * overwriting it + */ + + if (flags & HX509_CERTS_CREATE) { + /* + * Note that the file creation is deferred until file_store() is + * called. + */ + ret = hx509_certs_init(context, "MEMORY:ks-file-create", + 0, lock, &ksf->certs); + if (ret) + goto out; + *data = ksf; + return 0; + } + + ret = _hx509_collector_alloc(context, lock, &pem_ctx.c); + if (ret) + goto out; + + for (p = ksf->fn; p != NULL; p = pnext) { + FILE *f; + + pnext = strchr(p, ','); + if (pnext) + *pnext++ = '\0'; + + + if ((f = fopen(p, "r")) == NULL) { + ret = ENOENT; + hx509_set_error_string(context, 0, ret, + "Failed to open PEM file \"%s\": %s", + p, strerror(errno)); + goto out; + } + rk_cloexec_file(f); + + ret = hx509_pem_read(context, f, pem_func, &pem_ctx); + fclose(f); + if (ret != 0 && ret != HX509_PARSING_KEY_FAILED) + goto out; + else if (ret == HX509_PARSING_KEY_FAILED) { + size_t length; + void *ptr; + size_t i; + + ret = rk_undumpdata(p, &ptr, &length); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + + for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) { + const AlgorithmIdentifier *ai = NULL; + + if (formats[i].ai != NULL) + ai = (*formats[i].ai)(); + + ret = (*formats[i].func)(context, p, pem_ctx.flags, pem_ctx.c, + NULL, ptr, length, ai); + if (ret == 0) + break; + } + rk_xfree(ptr); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + } + } + + ret = _hx509_collector_collect_certs(context, pem_ctx.c, &ksf->certs); + if (ret) + goto out; + + ret = _hx509_collector_collect_private_keys(context, pem_ctx.c, &keys); + if (ret == 0) { + int i; + + for (i = 0; keys[i]; i++) + _hx509_certs_keys_add(context, ksf->certs, keys[i]); + _hx509_certs_keys_free(context, keys); + } + +out: + if (ret == 0) + *data = ksf; + else { + if (ksf->fn) + free(ksf->fn); + free(ksf); + } + if (pem_ctx.c) + _hx509_collector_free(pem_ctx.c); + + return ret; +} + +static int +file_init_pem(hx509_context context, + hx509_certs certs, void **data, int flags, + const char *residue, hx509_lock lock) +{ + return file_init_common(context, certs, data, flags, residue, lock, USE_PEM); +} + +static int +file_init_der(hx509_context context, + hx509_certs certs, void **data, int flags, + const char *residue, hx509_lock lock) +{ + return file_init_common(context, certs, data, flags, residue, lock, USE_DER); +} + +static int +file_free(hx509_certs certs, void *data) +{ + struct ks_file *ksf = data; + hx509_certs_free(&ksf->certs); + free(ksf->fn); + free(ksf); + return 0; +} + +struct store_ctx { + FILE *f; + outformat format; + int store_flags; +}; + +static int HX509_LIB_CALL +store_func(hx509_context context, void *ctx, hx509_cert c) +{ + struct store_ctx *sc = ctx; + heim_octet_string data; + int ret = 0; + + if (hx509_cert_have_private_key_only(c)) { + data.length = 0; + data.data = NULL; + } else { + ret = hx509_cert_binary(context, c, &data); + if (ret) + return ret; + } + + switch (sc->format) { + case USE_DER: + /* Can't store both. Well, we could, but nothing will support it */ + if (data.data) { + fwrite(data.data, data.length, 1, sc->f); + } else if (_hx509_cert_private_key_exportable(c) && + !(sc->store_flags & HX509_CERTS_STORE_NO_PRIVATE_KEYS)) { + hx509_private_key key = _hx509_cert_private_key(c); + + free(data.data); + data.length = 0; + data.data = NULL; + ret = _hx509_private_key_export(context, key, + HX509_KEY_FORMAT_DER, &data); + if (ret == 0 && data.length) + fwrite(data.data, data.length, 1, sc->f); + } + break; + case USE_PEM: + if (_hx509_cert_private_key_exportable(c) && + !(sc->store_flags & HX509_CERTS_STORE_NO_PRIVATE_KEYS)) { + heim_octet_string priv_key; + hx509_private_key key = _hx509_cert_private_key(c); + + ret = _hx509_private_key_export(context, key, + HX509_KEY_FORMAT_DER, &priv_key); + if (ret == 0) + ret = hx509_pem_write(context, _hx509_private_pem_name(key), NULL, + sc->f, priv_key.data, priv_key.length); + free(priv_key.data); + } + if (ret == 0 && data.data) { + ret = hx509_pem_write(context, "CERTIFICATE", NULL, sc->f, + data.data, data.length); + } + break; + } + + free(data.data); + return ret; +} + +static int +mk_temp(const char *fn, char **tfn) +{ + char *ds; + int ret = -1; + +#ifdef WIN32 + char buf[PATH_MAX]; + char *p; + + *tfn = NULL; + + if ((ds = _fullpath(buf, fn, sizeof(buf))) == NULL) { + errno = errno ? errno : ENAMETOOLONG; + return -1; + } + + if ((p = strrchr(ds, '\\')) == NULL) { + ret = asprintf(tfn, ".%s-XXXXXX", ds); /* XXX can't happen */ + } else { + *(p++) = '\0'; + ret = asprintf(tfn, "%s/.%s-XXXXXX", ds, p); + } +#else + *tfn = NULL; + if ((ds = strdup(fn))) + ret = asprintf(tfn, "%s/.%s-XXXXXX", dirname(ds), basename(ds)); + free(ds); +#endif + + /* + * Using mkostemp() risks leaving garbage files lying around. To do better + * without resorting to file locks (which have their own problems) we need + * O_TMPFILE and linkat(2), which only Linux has. + */ + return (ret == -1 || *tfn == NULL) ? -1 : mkostemp(*tfn, O_CLOEXEC); +} + +static int +file_store(hx509_context context, + hx509_certs certs, void *data, int flags, hx509_lock lock) +{ + struct ks_file *ksf = data; + struct store_ctx sc; + char *tfn; + int ret; + int fd; + + sc.f = NULL; + fd = mk_temp(ksf->fn, &tfn); + if (fd > -1) + sc.f = fdopen(fd, "w"); + if (sc.f == NULL) { + hx509_set_error_string(context, 0, ret = errno, + "Failed to open file %s for writing", ksf->fn); + if (fd > -1) + (void) close(fd); + return ret; + } + rk_cloexec_file(sc.f); + sc.store_flags = flags; + sc.format = ksf->format; + + ret = hx509_certs_iter_f(context, ksf->certs, store_func, &sc); + if (ret == 0) + ret = fclose(sc.f); + else + (void) fclose(sc.f); + if (ret) + (void) unlink(tfn); + else + (void) rename(tfn, ksf->fn); + free(tfn); + return ret; +} + +static int +file_add(hx509_context context, hx509_certs certs, void *data, hx509_cert c) +{ + struct ks_file *ksf = data; + return hx509_certs_add(context, ksf->certs, c); +} + +static int +file_iter_start(hx509_context context, + hx509_certs certs, void *data, void **cursor) +{ + struct ks_file *ksf = data; + return hx509_certs_start_seq(context, ksf->certs, cursor); +} + +static int +file_iter(hx509_context context, + hx509_certs certs, void *data, void *iter, hx509_cert *cert) +{ + struct ks_file *ksf = data; + return hx509_certs_next_cert(context, ksf->certs, iter, cert); +} + +static int +file_iter_end(hx509_context context, + hx509_certs certs, + void *data, + void *cursor) +{ + struct ks_file *ksf = data; + return hx509_certs_end_seq(context, ksf->certs, cursor); +} + +static int +file_getkeys(hx509_context context, + hx509_certs certs, + void *data, + hx509_private_key **keys) +{ + struct ks_file *ksf = data; + return _hx509_certs_keys_get(context, ksf->certs, keys); +} + +static int +file_addkey(hx509_context context, + hx509_certs certs, + void *data, + hx509_private_key key) +{ + struct ks_file *ksf = data; + return _hx509_certs_keys_add(context, ksf->certs, key); +} + +static int +file_destroy(hx509_context context, + hx509_certs certs, + void *data) +{ + struct ks_file *ksf = data; + return _hx509_erase_file(context, ksf->fn); +} + +static struct hx509_keyset_ops keyset_file = { + "FILE", + 0, + file_init_pem, + file_store, + file_free, + file_add, + NULL, + file_iter_start, + file_iter, + file_iter_end, + NULL, + file_getkeys, + file_addkey, + file_destroy +}; + +static struct hx509_keyset_ops keyset_pemfile = { + "PEM-FILE", + 0, + file_init_pem, + file_store, + file_free, + file_add, + NULL, + file_iter_start, + file_iter, + file_iter_end, + NULL, + file_getkeys, + file_addkey, + file_destroy +}; + +static struct hx509_keyset_ops keyset_derfile = { + "DER-FILE", + 0, + file_init_der, + file_store, + file_free, + file_add, + NULL, + file_iter_start, + file_iter, + file_iter_end, + NULL, + file_getkeys, + file_addkey, + file_destroy +}; + + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_ks_file_register(hx509_context context) +{ + _hx509_ks_register(context, &keyset_file); + _hx509_ks_register(context, &keyset_pemfile); + _hx509_ks_register(context, &keyset_derfile); +} diff --git a/third_party/heimdal/lib/hx509/ks_keychain.c b/third_party/heimdal/lib/hx509/ks_keychain.c new file mode 100644 index 0000000..3243ee8 --- /dev/null +++ b/third_party/heimdal/lib/hx509/ks_keychain.c @@ -0,0 +1,627 @@ +/* + * Copyright (c) 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" + +#ifdef HAVE_FRAMEWORK_SECURITY + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#include <Security/Security.h> + +/* Missing function decls in pre Leopard */ +#ifdef NEED_SECKEYGETCSPHANDLE_PROTO +OSStatus SecKeyGetCSPHandle(SecKeyRef, CSSM_CSP_HANDLE *); +OSStatus SecKeyGetCredentials(SecKeyRef, CSSM_ACL_AUTHORIZATION_TAG, + int, const CSSM_ACCESS_CREDENTIALS **); +#define kSecCredentialTypeDefault 0 +#define CSSM_SIZE uint32_t +#endif + + +static int +getAttribute(SecKeychainItemRef itemRef, SecItemAttr item, + SecKeychainAttributeList **attrs) +{ + SecKeychainAttributeInfo attrInfo; + UInt32 attrFormat = 0; + OSStatus ret; + + *attrs = NULL; + + attrInfo.count = 1; + attrInfo.tag = &item; + attrInfo.format = &attrFormat; + + ret = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL, + attrs, NULL, NULL); + if (ret) + return EINVAL; + return 0; +} + + +/* + * + */ + +struct kc_rsa { + SecKeychainItemRef item; + size_t keysize; +}; + + +static int +kc_rsa_public_encrypt(int flen, + const unsigned char *from, + unsigned char *to, + RSA *rsa, + int padding) +{ + return -1; +} + +static int +kc_rsa_public_decrypt(int flen, + const unsigned char *from, + unsigned char *to, + RSA *rsa, + int padding) +{ + return -1; +} + + +static int +kc_rsa_private_encrypt(int flen, + const unsigned char *from, + unsigned char *to, + RSA *rsa, + int padding) +{ + struct kc_rsa *kc = RSA_get_app_data(rsa); + + CSSM_RETURN cret; + OSStatus ret; + const CSSM_ACCESS_CREDENTIALS *creds; + SecKeyRef privKeyRef = (SecKeyRef)kc->item; + CSSM_CSP_HANDLE cspHandle; + const CSSM_KEY *cssmKey; + CSSM_CC_HANDLE sigHandle = 0; + CSSM_DATA sig, in; + int fret = 0; + + if (padding != RSA_PKCS1_PADDING) + return -1; + + cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey); + if(cret) abort(); + + cret = SecKeyGetCSPHandle(privKeyRef, &cspHandle); + if(cret) abort(); + + ret = SecKeyGetCredentials(privKeyRef, CSSM_ACL_AUTHORIZATION_SIGN, + kSecCredentialTypeDefault, &creds); + if(ret) abort(); + + ret = CSSM_CSP_CreateSignatureContext(cspHandle, CSSM_ALGID_RSA, + creds, cssmKey, &sigHandle); + if(ret) abort(); + + in.Data = (uint8 *)from; + in.Length = flen; + + sig.Data = (uint8 *)to; + sig.Length = kc->keysize; + + cret = CSSM_SignData(sigHandle, &in, 1, CSSM_ALGID_NONE, &sig); + if(cret) { + /* cssmErrorString(cret); */ + fret = -1; + } else + fret = sig.Length; + + if(sigHandle) + CSSM_DeleteContext(sigHandle); + + return fret; +} + +static int +kc_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to, + RSA * rsa, int padding) +{ + struct kc_rsa *kc = RSA_get_app_data(rsa); + + CSSM_RETURN cret; + OSStatus ret; + const CSSM_ACCESS_CREDENTIALS *creds; + SecKeyRef privKeyRef = (SecKeyRef)kc->item; + CSSM_CSP_HANDLE cspHandle; + const CSSM_KEY *cssmKey; + CSSM_CC_HANDLE handle = 0; + CSSM_DATA out, in, rem; + int fret = 0; + CSSM_SIZE outlen = 0; + char remdata[1024]; + + if (padding != RSA_PKCS1_PADDING) + return -1; + + cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey); + if(cret) abort(); + + cret = SecKeyGetCSPHandle(privKeyRef, &cspHandle); + if(cret) abort(); + + ret = SecKeyGetCredentials(privKeyRef, CSSM_ACL_AUTHORIZATION_DECRYPT, + kSecCredentialTypeDefault, &creds); + if(ret) abort(); + + + ret = CSSM_CSP_CreateAsymmetricContext (cspHandle, + CSSM_ALGID_RSA, + creds, + cssmKey, + CSSM_PADDING_PKCS1, + &handle); + if(ret) abort(); + + in.Data = (uint8 *)from; + in.Length = flen; + + out.Data = (uint8 *)to; + out.Length = kc->keysize; + + rem.Data = (uint8 *)remdata; + rem.Length = sizeof(remdata); + + cret = CSSM_DecryptData(handle, &in, 1, &out, 1, &outlen, &rem); + if(cret) { + /* cssmErrorString(cret); */ + fret = -1; + } else + fret = out.Length; + + if(handle) + CSSM_DeleteContext(handle); + + return fret; +} + +static int +kc_rsa_init(RSA *rsa) +{ + return 1; +} + +static int +kc_rsa_finish(RSA *rsa) +{ + struct kc_rsa *kc_rsa = RSA_get_app_data(rsa); + CFRelease(kc_rsa->item); + memset(kc_rsa, 0, sizeof(*kc_rsa)); + free(kc_rsa); + return 1; +} + +static const RSA_METHOD kc_rsa_pkcs1_method = { + "hx509 Keychain PKCS#1 RSA", + kc_rsa_public_encrypt, + kc_rsa_public_decrypt, + kc_rsa_private_encrypt, + kc_rsa_private_decrypt, + NULL, + NULL, + kc_rsa_init, + kc_rsa_finish, + 0, + NULL, + NULL, + NULL, + NULL +}; + +static int +set_private_key(hx509_context context, + SecKeychainItemRef itemRef, + hx509_cert cert) +{ + struct kc_rsa *kc; + hx509_private_key key; + RSA *rsa; + int ret; + + ret = hx509_private_key_init(&key, NULL, NULL); + if (ret) + return ret; + + kc = calloc(1, sizeof(*kc)); + if (kc == NULL) + _hx509_abort("out of memory"); + + kc->item = itemRef; + + rsa = RSA_new(); + if (rsa == NULL) + _hx509_abort("out of memory"); + + /* Argh, fake modulus since OpenSSL API is on crack */ + { + SecKeychainAttributeList *attrs = NULL; + uint32_t size; + void *data; + + rsa->n = BN_new(); + if (rsa->n == NULL) abort(); + + ret = getAttribute(itemRef, kSecKeyKeySizeInBits, &attrs); + if (ret) abort(); + + size = *(uint32_t *)attrs->attr[0].data; + SecKeychainItemFreeAttributesAndData(attrs, NULL); + + kc->keysize = (size + 7) / 8; + + data = malloc(kc->keysize); + memset(data, 0xe0, kc->keysize); + BN_bin2bn(data, kc->keysize, rsa->n); + free(data); + } + rsa->e = NULL; + + RSA_set_method(rsa, &kc_rsa_pkcs1_method); + ret = RSA_set_app_data(rsa, kc); + if (ret != 1) + _hx509_abort("RSA_set_app_data"); + + hx509_private_key_assign_rsa(key, rsa); + _hx509_cert_assign_key(cert, key); + + return 0; +} + +/* + * + */ + +struct ks_keychain { + int anchors; + SecKeychainRef keychain; +}; + +static int +keychain_init(hx509_context context, + hx509_certs certs, void **data, int flags, + const char *residue, hx509_lock lock) +{ + struct ks_keychain *ctx; + + if (flags & HX509_CERTS_NO_PRIVATE_KEYS) { + hx509_set_error_string(context, 0, ENOTSUP, + "KEYCHAIN store does not support not reading " + "private keys"); + return ENOTSUP; + } + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + hx509_clear_error_string(context); + return ENOMEM; + } + + if (residue) { + if (strcasecmp(residue, "system-anchors") == 0) { + ctx->anchors = 1; + } else if (strncasecmp(residue, "FILE:", 5) == 0) { + OSStatus ret; + + ret = SecKeychainOpen(residue + 5, &ctx->keychain); + if (ret != noErr) { + hx509_set_error_string(context, 0, ENOENT, + "Failed to open %s", residue); + free(ctx); + return ENOENT; + } + } else { + hx509_set_error_string(context, 0, ENOENT, + "Unknown subtype %s", residue); + free(ctx); + return ENOENT; + } + } + + *data = ctx; + return 0; +} + +/* + * + */ + +static int +keychain_free(hx509_certs certs, void *data) +{ + struct ks_keychain *ctx = data; + if (ctx->keychain) + CFRelease(ctx->keychain); + memset(ctx, 0, sizeof(*ctx)); + free(ctx); + return 0; +} + +/* + * + */ + +struct iter { + hx509_certs certs; + void *cursor; + SecKeychainSearchRef searchRef; +}; + +static int +keychain_iter_start(hx509_context context, + hx509_certs certs, void *data, void **cursor) +{ + struct ks_keychain *ctx = data; + struct iter *iter; + + iter = calloc(1, sizeof(*iter)); + if (iter == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + + if (ctx->anchors) { + CFArrayRef anchors; + int ret; + int i; + + ret = hx509_certs_init(context, "MEMORY:ks-file-create", + 0, NULL, &iter->certs); + if (ret) { + free(iter); + return ret; + } + + ret = SecTrustCopyAnchorCertificates(&anchors); + if (ret != 0) { + hx509_certs_free(&iter->certs); + free(iter); + hx509_set_error_string(context, 0, ENOMEM, + "Can't get trust anchors from Keychain"); + return ENOMEM; + } + for (i = 0; i < CFArrayGetCount(anchors); i++) { + SecCertificateRef cr; + hx509_cert cert; + CSSM_DATA cssm; + + cr = (SecCertificateRef)CFArrayGetValueAtIndex(anchors, i); + + SecCertificateGetData(cr, &cssm); + + cert = hx509_cert_init_data(context, cssm.Data, cssm.Length, NULL); + if (cert == NULL) + continue; + + ret = hx509_certs_add(context, iter->certs, cert); + hx509_cert_free(cert); + } + CFRelease(anchors); + } + + if (iter->certs) { + int ret; + ret = hx509_certs_start_seq(context, iter->certs, &iter->cursor); + if (ret) { + hx509_certs_free(&iter->certs); + free(iter); + return ret; + } + } else { + OSStatus ret; + + ret = SecKeychainSearchCreateFromAttributes(ctx->keychain, + kSecCertificateItemClass, + NULL, + &iter->searchRef); + if (ret) { + free(iter); + hx509_set_error_string(context, 0, ret, + "Failed to start search for attributes"); + return ENOMEM; + } + } + + *cursor = iter; + return 0; +} + +/* + * + */ + +static int +keychain_iter(hx509_context context, + hx509_certs certs, void *data, void *cursor, hx509_cert *cert) +{ + SecKeychainAttributeList *attrs = NULL; + SecKeychainAttributeInfo attrInfo; + UInt32 attrFormat[1] = { 0 }; + SecKeychainItemRef itemRef; + SecItemAttr item[1]; + heim_error_t error = NULL; + struct iter *iter = cursor; + OSStatus ret; + UInt32 len; + void *ptr = NULL; + + if (iter->certs) + return hx509_certs_next_cert(context, iter->certs, iter->cursor, cert); + + *cert = NULL; + + ret = SecKeychainSearchCopyNext(iter->searchRef, &itemRef); + if (ret == errSecItemNotFound) + return 0; + else if (ret != 0) + return EINVAL; + + /* + * Pick out certificate and matching "keyid" + */ + + item[0] = kSecPublicKeyHashItemAttr; + + attrInfo.count = 1; + attrInfo.tag = item; + attrInfo.format = attrFormat; + + ret = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL, + &attrs, &len, &ptr); + if (ret) + return EINVAL; + + *cert = hx509_cert_init_data(context, ptr, len, &error); + if (*cert == NULL) { + ret = heim_error_get_code(error); + heim_release(error); + goto out; + } + + /* + * Find related private key if there is one by looking at + * kSecPublicKeyHashItemAttr == kSecKeyLabel + */ + { + SecKeychainSearchRef search; + SecKeychainAttribute attrKeyid; + SecKeychainAttributeList attrList; + + attrKeyid.tag = kSecKeyLabel; + attrKeyid.length = attrs->attr[0].length; + attrKeyid.data = attrs->attr[0].data; + + attrList.count = 1; + attrList.attr = &attrKeyid; + + ret = SecKeychainSearchCreateFromAttributes(NULL, + CSSM_DL_DB_RECORD_PRIVATE_KEY, + &attrList, + &search); + if (ret) { + ret = 0; + goto out; + } + + ret = SecKeychainSearchCopyNext(search, &itemRef); + CFRelease(search); + if (ret == errSecItemNotFound) { + ret = 0; + goto out; + } else if (ret) { + ret = EINVAL; + goto out; + } + set_private_key(context, itemRef, *cert); + } + +out: + SecKeychainItemFreeAttributesAndData(attrs, ptr); + + return ret; +} + +/* + * + */ + +static int +keychain_iter_end(hx509_context context, + hx509_certs certs, + void *data, + void *cursor) +{ + struct iter *iter = cursor; + + if (iter->certs) { + hx509_certs_end_seq(context, iter->certs, iter->cursor); + hx509_certs_free(&iter->certs); + } else { + CFRelease(iter->searchRef); + } + + memset(iter, 0, sizeof(*iter)); + free(iter); + return 0; +} + +/* + * + */ + +struct hx509_keyset_ops keyset_keychain = { + "KEYCHAIN", + 0, + keychain_init, + NULL, + keychain_free, + NULL, + NULL, + keychain_iter_start, + keychain_iter, + keychain_iter_end, + NULL, + NULL, + NULL, + NULL +}; + +#pragma clang diagnostic pop + +#endif /* HAVE_FRAMEWORK_SECURITY */ + +/* + * + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_ks_keychain_register(hx509_context context) +{ +#ifdef HAVE_FRAMEWORK_SECURITY + _hx509_ks_register(context, &keyset_keychain); +#endif +} diff --git a/third_party/heimdal/lib/hx509/ks_mem.c b/third_party/heimdal/lib/hx509/ks_mem.c new file mode 100644 index 0000000..f325d12 --- /dev/null +++ b/third_party/heimdal/lib/hx509/ks_mem.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2005 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" + +/* + * Should use two hash/tree certificates intead of a array. Criteria + * should be subject and subjectKeyIdentifier since those two are + * commonly seached on in CMS and path building. + */ + +struct mem_data { + char *name; + struct { + unsigned long len; + hx509_cert *val; + } certs; + hx509_private_key *keys; +}; + +static int +mem_init(hx509_context context, + hx509_certs certs, void **data, int flags, + const char *residue, hx509_lock lock) +{ + struct mem_data *mem; + mem = calloc(1, sizeof(*mem)); + if (mem == NULL) + return ENOMEM; + if (residue == NULL || residue[0] == '\0') + residue = "anonymous"; + mem->name = strdup(residue); + if (mem->name == NULL) { + free(mem); + return ENOMEM; + } + *data = mem; + return 0; +} + +static int +mem_free(hx509_certs certs, void *data) +{ + struct mem_data *mem = data; + unsigned long i; + + for (i = 0; i < mem->certs.len; i++) + hx509_cert_free(mem->certs.val[i]); + free(mem->certs.val); + for (i = 0; mem->keys && mem->keys[i]; i++) + hx509_private_key_free(&mem->keys[i]); + free(mem->keys); + free(mem->name); + free(mem); + + return 0; +} + +static int +mem_add(hx509_context context, hx509_certs certs, void *data, hx509_cert c) +{ + struct mem_data *mem = data; + hx509_cert *val; + + val = realloc(mem->certs.val, + (mem->certs.len + 1) * sizeof(mem->certs.val[0])); + if (val == NULL) + return ENOMEM; + + mem->certs.val = val; + mem->certs.val[mem->certs.len] = hx509_cert_ref(c); + mem->certs.len++; + + return 0; +} + +static int +mem_iter_start(hx509_context context, + hx509_certs certs, + void *data, + void **cursor) +{ + unsigned long *iter = malloc(sizeof(*iter)); + + if (iter == NULL) + return ENOMEM; + + *iter = 0; + *cursor = iter; + + return 0; +} + +static int +mem_iter(hx509_context contexst, + hx509_certs certs, + void *data, + void *cursor, + hx509_cert *cert) +{ + unsigned long *iter = cursor; + struct mem_data *mem = data; + + if (*iter >= mem->certs.len) { + *cert = NULL; + return 0; + } + + *cert = hx509_cert_ref(mem->certs.val[*iter]); + (*iter)++; + return 0; +} + +static int +mem_iter_end(hx509_context context, + hx509_certs certs, + void *data, + void *cursor) +{ + free(cursor); + return 0; +} + +static int +mem_getkeys(hx509_context context, + hx509_certs certs, + void *data, + hx509_private_key **keys) +{ + struct mem_data *mem = data; + int i; + + for (i = 0; mem->keys && mem->keys[i]; i++) + ; + *keys = calloc(i + 1, sizeof(**keys)); + for (i = 0; mem->keys && mem->keys[i]; i++) { + (*keys)[i] = _hx509_private_key_ref(mem->keys[i]); + if ((*keys)[i] == NULL) { + while (--i >= 0) + hx509_private_key_free(&(*keys)[i]); + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + } + (*keys)[i] = NULL; + return 0; +} + +static int +mem_addkey(hx509_context context, + hx509_certs certs, + void *data, + hx509_private_key key) +{ + struct mem_data *mem = data; + void *ptr; + int i; + + for (i = 0; mem->keys && mem->keys[i]; i++) + ; + ptr = realloc(mem->keys, (i + 2) * sizeof(*mem->keys)); + if (ptr == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + mem->keys = ptr; + mem->keys[i] = _hx509_private_key_ref(key); + mem->keys[i + 1] = NULL; + return 0; +} + + +static struct hx509_keyset_ops keyset_mem = { + "MEMORY", + 0, + mem_init, + NULL, + mem_free, + mem_add, + NULL, + mem_iter_start, + mem_iter, + mem_iter_end, + NULL, + mem_getkeys, + mem_addkey, + NULL +}; + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_ks_mem_register(hx509_context context) +{ + _hx509_ks_register(context, &keyset_mem); +} diff --git a/third_party/heimdal/lib/hx509/ks_null.c b/third_party/heimdal/lib/hx509/ks_null.c new file mode 100644 index 0000000..c241d30 --- /dev/null +++ b/third_party/heimdal/lib/hx509/ks_null.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2005 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" + + +static int +null_init(hx509_context context, + hx509_certs certs, void **data, int flags, + const char *residue, hx509_lock lock) +{ + *data = NULL; + return 0; +} + +static int +null_free(hx509_certs certs, void *data) +{ + assert(data == NULL); + return 0; +} + +static int +null_iter_start(hx509_context context, + hx509_certs certs, void *data, void **cursor) +{ + *cursor = NULL; + return 0; +} + +static int +null_iter(hx509_context context, + hx509_certs certs, void *data, void *iter, hx509_cert *cert) +{ + *cert = NULL; + return ENOENT; +} + +static int +null_iter_end(hx509_context context, + hx509_certs certs, + void *data, + void *cursor) +{ + assert(cursor == NULL); + return 0; +} + + +struct hx509_keyset_ops keyset_null = { + "NULL", + 0, + null_init, + NULL, + null_free, + NULL, + NULL, + null_iter_start, + null_iter, + null_iter_end, + NULL, + NULL, + NULL, + NULL +}; + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_ks_null_register(hx509_context context) +{ + _hx509_ks_register(context, &keyset_null); +} diff --git a/third_party/heimdal/lib/hx509/ks_p11.c b/third_party/heimdal/lib/hx509/ks_p11.c new file mode 100644 index 0000000..265523b --- /dev/null +++ b/third_party/heimdal/lib/hx509/ks_p11.c @@ -0,0 +1,1230 @@ +/* + * Copyright (c) 2004 - 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" + +#ifdef HAVE_DLOPEN + +#include "ref/pkcs11.h" + +struct p11_slot { + uint64_t flags; +#define P11_SESSION 1 +#define P11_SESSION_IN_USE 2 +#define P11_LOGIN_REQ 4 +#define P11_LOGIN_DONE 8 +#define P11_TOKEN_PRESENT 16 + CK_SESSION_HANDLE session; + CK_SLOT_ID id; + CK_BBOOL token; + char *name; + hx509_certs certs; + char *pin; + struct { + CK_MECHANISM_TYPE_PTR list; + CK_ULONG num; + CK_MECHANISM_INFO_PTR *infos; + } mechs; +}; + +struct p11_module { + void *dl_handle; + CK_FUNCTION_LIST_PTR funcs; + CK_ULONG num_slots; + unsigned int ref; + unsigned int selected_slot; + struct p11_slot *slot; +}; + +#define P11FUNC(module,f,args) (*(module)->funcs->C_##f)args + +static int p11_get_session(hx509_context, + struct p11_module *, + struct p11_slot *, + hx509_lock, + CK_SESSION_HANDLE *); +static int p11_put_session(struct p11_module *, + struct p11_slot *, + CK_SESSION_HANDLE); +static void p11_release_module(struct p11_module *); + +static int p11_list_keys(hx509_context, + struct p11_module *, + struct p11_slot *, + CK_SESSION_HANDLE, + hx509_lock, + hx509_certs *); + +/* + * + */ + +struct p11_rsa { + struct p11_module *p; + struct p11_slot *slot; + CK_OBJECT_HANDLE private_key; + CK_OBJECT_HANDLE public_key; +}; + +static int +p11_rsa_public_encrypt(int flen, + const unsigned char *from, + unsigned char *to, + RSA *rsa, + int padding) +{ + return -1; +} + +static int +p11_rsa_public_decrypt(int flen, + const unsigned char *from, + unsigned char *to, + RSA *rsa, + int padding) +{ + return -1; +} + + +static int +p11_rsa_private_encrypt(int flen, + const unsigned char *from, + unsigned char *to, + RSA *rsa, + int padding) +{ + struct p11_rsa *p11rsa = RSA_get_app_data(rsa); + CK_OBJECT_HANDLE key = p11rsa->private_key; + CK_SESSION_HANDLE session; + CK_MECHANISM mechanism; + CK_ULONG ck_sigsize; + int ret; + + if (padding != RSA_PKCS1_PADDING) + return -1; + + memset(&mechanism, 0, sizeof(mechanism)); + mechanism.mechanism = CKM_RSA_PKCS; + + ck_sigsize = RSA_size(rsa); + + ret = p11_get_session(NULL, p11rsa->p, p11rsa->slot, NULL, &session); + if (ret) + return -1; + + ret = P11FUNC(p11rsa->p, SignInit, (session, &mechanism, key)); + if (ret != CKR_OK) { + p11_put_session(p11rsa->p, p11rsa->slot, session); + return -1; + } + + ret = P11FUNC(p11rsa->p, Sign, + (session, (CK_BYTE *)(intptr_t)from, flen, to, &ck_sigsize)); + p11_put_session(p11rsa->p, p11rsa->slot, session); + if (ret != CKR_OK) + return -1; + + return ck_sigsize; +} + +static int +p11_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to, + RSA * rsa, int padding) +{ + struct p11_rsa *p11rsa = RSA_get_app_data(rsa); + CK_OBJECT_HANDLE key = p11rsa->private_key; + CK_SESSION_HANDLE session; + CK_MECHANISM mechanism; + CK_ULONG ck_sigsize; + int ret; + + if (padding != RSA_PKCS1_PADDING) + return -1; + + memset(&mechanism, 0, sizeof(mechanism)); + mechanism.mechanism = CKM_RSA_PKCS; + + ck_sigsize = RSA_size(rsa); + + ret = p11_get_session(NULL, p11rsa->p, p11rsa->slot, NULL, &session); + if (ret) + return -1; + + ret = P11FUNC(p11rsa->p, DecryptInit, (session, &mechanism, key)); + if (ret != CKR_OK) { + p11_put_session(p11rsa->p, p11rsa->slot, session); + return -1; + } + + ret = P11FUNC(p11rsa->p, Decrypt, + (session, (CK_BYTE *)(intptr_t)from, flen, to, &ck_sigsize)); + p11_put_session(p11rsa->p, p11rsa->slot, session); + if (ret != CKR_OK) + return -1; + + return ck_sigsize; +} + +static int +p11_rsa_init(RSA *rsa) +{ + return 1; +} + +static int +p11_rsa_finish(RSA *rsa) +{ + struct p11_rsa *p11rsa = RSA_get_app_data(rsa); + p11_release_module(p11rsa->p); + free(p11rsa); + return 1; +} + +static const RSA_METHOD p11_rsa_pkcs1_method = { + "hx509 PKCS11 PKCS#1 RSA", + p11_rsa_public_encrypt, + p11_rsa_public_decrypt, + p11_rsa_private_encrypt, + p11_rsa_private_decrypt, + NULL, + NULL, + p11_rsa_init, + p11_rsa_finish, + 0, + NULL, + NULL, + NULL, + NULL +}; + +/* + * + */ + +static int +p11_mech_info(hx509_context context, + struct p11_module *p, + struct p11_slot *slot, + int num) +{ + CK_ULONG i; + int ret; + + ret = P11FUNC(p, GetMechanismList, (slot->id, NULL_PTR, &i)); + if (ret) { + hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH, + "Failed to get mech list count for slot %d", + num); + return HX509_PKCS11_NO_MECH; + } + if (i == 0) { + hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH, + "no mech supported for slot %d", num); + return HX509_PKCS11_NO_MECH; + } + slot->mechs.list = calloc(i, sizeof(slot->mechs.list[0])); + if (slot->mechs.list == NULL) { + hx509_set_error_string(context, 0, ENOMEM, + "out of memory"); + return ENOMEM; + } + slot->mechs.num = i; + ret = P11FUNC(p, GetMechanismList, (slot->id, slot->mechs.list, &i)); + if (ret) { + hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH, + "Failed to get mech list for slot %d", + num); + return HX509_PKCS11_NO_MECH; + } + assert(i == slot->mechs.num); + + slot->mechs.infos = calloc(i, sizeof(*slot->mechs.infos)); + if (slot->mechs.list == NULL) { + hx509_set_error_string(context, 0, ENOMEM, + "out of memory"); + return ENOMEM; + } + + for (i = 0; i < slot->mechs.num; i++) { + slot->mechs.infos[i] = calloc(1, sizeof(*(slot->mechs.infos[0]))); + if (slot->mechs.infos[i] == NULL) { + hx509_set_error_string(context, 0, ENOMEM, + "out of memory"); + return ENOMEM; + } + ret = P11FUNC(p, GetMechanismInfo, (slot->id, slot->mechs.list[i], + slot->mechs.infos[i])); + if (ret) { + hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH, + "Failed to get mech info for slot %d", + num); + return HX509_PKCS11_NO_MECH; + } + } + + return 0; +} + +static int +p11_init_slot(hx509_context context, + struct p11_module *p, + hx509_lock lock, + CK_SLOT_ID id, + int num, + struct p11_slot *slot) +{ + CK_SESSION_HANDLE session; + CK_SLOT_INFO slot_info; + CK_TOKEN_INFO token_info; + size_t i; + int ret; + + slot->certs = NULL; + slot->id = id; + + ret = P11FUNC(p, GetSlotInfo, (slot->id, &slot_info)); + if (ret) { + hx509_set_error_string(context, 0, HX509_PKCS11_TOKEN_CONFUSED, + "Failed to init PKCS11 slot %d", + num); + return HX509_PKCS11_TOKEN_CONFUSED; + } + + for (i = sizeof(slot_info.slotDescription) - 1; i > 0; i--) { + char c = slot_info.slotDescription[i]; + if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\0') + continue; + i++; + break; + } + + ret = asprintf(&slot->name, "%.*s", (int)i, + slot_info.slotDescription); + if (ret == -1) + return ENOMEM; + + if ((slot_info.flags & CKF_TOKEN_PRESENT) == 0) + return 0; + + ret = P11FUNC(p, GetTokenInfo, (slot->id, &token_info)); + if (ret) { + hx509_set_error_string(context, 0, HX509_PKCS11_NO_TOKEN, + "Failed to init PKCS11 slot %d " + "with error 0x%08x", + num, ret); + return HX509_PKCS11_NO_TOKEN; + } + slot->flags |= P11_TOKEN_PRESENT; + + if (token_info.flags & CKF_LOGIN_REQUIRED) + slot->flags |= P11_LOGIN_REQ; + + ret = p11_get_session(context, p, slot, lock, &session); + if (ret) + return ret; + + ret = p11_mech_info(context, p, slot, num); + if (ret) + goto out; + + ret = p11_list_keys(context, p, slot, session, lock, &slot->certs); + out: + p11_put_session(p, slot, session); + + return ret; +} + +static int +p11_get_session(hx509_context context, + struct p11_module *p, + struct p11_slot *slot, + hx509_lock lock, + CK_SESSION_HANDLE *psession) +{ + CK_RV ret; + + if (slot->flags & P11_SESSION_IN_USE) + _hx509_abort("slot already in session"); + + if (slot->flags & P11_SESSION) { + slot->flags |= P11_SESSION_IN_USE; + *psession = slot->session; + return 0; + } + + ret = P11FUNC(p, OpenSession, (slot->id, + CKF_SERIAL_SESSION, + NULL, + NULL, + &slot->session)); + if (ret != CKR_OK) { + if (context) + hx509_set_error_string(context, 0, HX509_PKCS11_OPEN_SESSION, + "Failed to OpenSession for slot id %d " + "with error: 0x%08x", + (int)slot->id, ret); + return HX509_PKCS11_OPEN_SESSION; + } + + slot->flags |= P11_SESSION; + + /* + * If we have have to login, and haven't tried before and have a + * prompter or known to work pin code. + * + * This code is very conversative and only uses the prompter in + * the hx509_lock, the reason is that it's bad to try many + * passwords on a pkcs11 token, it might lock up and have to be + * unlocked by a administrator. + * + * XXX try harder to not use pin several times on the same card. + */ + + if ( (slot->flags & P11_LOGIN_REQ) + && (slot->flags & P11_LOGIN_DONE) == 0 + && (lock || slot->pin)) + { + hx509_prompt prompt; + char pin[20]; + char *str; + + if (slot->pin == NULL) { + + memset(&prompt, 0, sizeof(prompt)); + + ret = asprintf(&str, "PIN code for %s: ", slot->name); + if (ret == -1 || str == NULL) { + if (context) + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + prompt.prompt = str; + prompt.type = HX509_PROMPT_TYPE_PASSWORD; + prompt.reply.data = pin; + prompt.reply.length = sizeof(pin); + + ret = hx509_lock_prompt(lock, &prompt); + if (ret) { + free(str); + if (context) + hx509_set_error_string(context, 0, ret, + "Failed to get pin code for slot " + "id %d with error: %d", + (int)slot->id, ret); + return ret; + } + free(str); + } else { + strlcpy(pin, slot->pin, sizeof(pin)); + } + + ret = P11FUNC(p, Login, (slot->session, CKU_USER, + (unsigned char*)pin, strlen(pin))); + if (ret != CKR_OK) { + if (context) + hx509_set_error_string(context, 0, HX509_PKCS11_LOGIN, + "Failed to login on slot id %d " + "with error: 0x%08x", + (int)slot->id, ret); + switch(ret) { + case CKR_PIN_LOCKED: + return HX509_PKCS11_PIN_LOCKED; + case CKR_PIN_EXPIRED: + return HX509_PKCS11_PIN_EXPIRED; + case CKR_PIN_INCORRECT: + return HX509_PKCS11_PIN_INCORRECT; + case CKR_USER_PIN_NOT_INITIALIZED: + return HX509_PKCS11_PIN_NOT_INITIALIZED; + default: + return HX509_PKCS11_LOGIN; + } + } else + slot->flags |= P11_LOGIN_DONE; + + if (slot->pin == NULL) { + slot->pin = strdup(pin); + if (slot->pin == NULL) { + if (context) + hx509_set_error_string(context, 0, ENOMEM, + "out of memory"); + return ENOMEM; + } + } + } else + slot->flags |= P11_LOGIN_DONE; + + slot->flags |= P11_SESSION_IN_USE; + + *psession = slot->session; + + return 0; +} + +static int +p11_put_session(struct p11_module *p, + struct p11_slot *slot, + CK_SESSION_HANDLE session) +{ + if ((slot->flags & P11_SESSION_IN_USE) == 0) + _hx509_abort("slot not in session"); + slot->flags &= ~P11_SESSION_IN_USE; + + return 0; +} + +static int +iterate_entries(hx509_context context, + struct p11_module *p, struct p11_slot *slot, + CK_SESSION_HANDLE session, + CK_ATTRIBUTE *search_data, int num_search_data, + CK_ATTRIBUTE *query, int num_query, + int (*func)(hx509_context, + struct p11_module *, struct p11_slot *, + CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + void *, CK_ATTRIBUTE *, int), void *ptr) +{ + CK_OBJECT_HANDLE object; + CK_ULONG object_count; + int ret, ret2, i; + + ret = P11FUNC(p, FindObjectsInit, (session, search_data, num_search_data)); + if (ret != CKR_OK) { + return -1; + } + while (1) { + ret = P11FUNC(p, FindObjects, (session, &object, 1, &object_count)); + if (ret != CKR_OK) { + return -1; + } + if (object_count == 0) + break; + + for (i = 0; i < num_query; i++) + query[i].pValue = NULL; + + ret = P11FUNC(p, GetAttributeValue, + (session, object, query, num_query)); + if (ret != CKR_OK) { + return -1; + } + for (i = 0; i < num_query; i++) { + query[i].pValue = malloc(query[i].ulValueLen); + if (query[i].pValue == NULL) { + ret = ENOMEM; + goto out; + } + } + ret = P11FUNC(p, GetAttributeValue, + (session, object, query, num_query)); + if (ret != CKR_OK) { + ret = -1; + goto out; + } + + ret = (*func)(context, p, slot, session, object, ptr, query, num_query); + if (ret) + goto out; + + for (i = 0; i < num_query; i++) { + if (query[i].pValue) + free(query[i].pValue); + query[i].pValue = NULL; + } + } + out: + + for (i = 0; i < num_query; i++) { + if (query[i].pValue) + free(query[i].pValue); + query[i].pValue = NULL; + } + + ret2 = P11FUNC(p, FindObjectsFinal, (session)); + if (ret2 != CKR_OK) { + return ret2; + } + + return ret; +} + +static BIGNUM * +getattr_bn(struct p11_module *p, + struct p11_slot *slot, + CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + unsigned int type) +{ + CK_ATTRIBUTE query; + BIGNUM *bn; + int ret; + + query.type = type; + query.pValue = NULL; + query.ulValueLen = 0; + + ret = P11FUNC(p, GetAttributeValue, + (session, object, &query, 1)); + if (ret != CKR_OK) + return NULL; + + query.pValue = malloc(query.ulValueLen); + + ret = P11FUNC(p, GetAttributeValue, + (session, object, &query, 1)); + if (ret != CKR_OK) { + free(query.pValue); + return NULL; + } + bn = BN_bin2bn(query.pValue, query.ulValueLen, NULL); + free(query.pValue); + + return bn; +} + +static int +collect_private_key(hx509_context context, + struct p11_module *p, struct p11_slot *slot, + CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + void *ptr, CK_ATTRIBUTE *query, int num_query) +{ + struct hx509_collector *collector = ptr; + hx509_private_key key; + heim_octet_string localKeyId; + int ret; + RSA *rsa; + struct p11_rsa *p11rsa; + + localKeyId.data = query[0].pValue; + localKeyId.length = query[0].ulValueLen; + + ret = hx509_private_key_init(&key, NULL, NULL); + if (ret) + return ret; + + rsa = RSA_new(); + if (rsa == NULL) + _hx509_abort("out of memory"); + + /* + * The exponent and modulus should always be present according to + * the pkcs11 specification, but some smartcards leaves it out, + * let ignore any failure to fetch it. + */ + rsa->n = getattr_bn(p, slot, session, object, CKA_MODULUS); + rsa->e = getattr_bn(p, slot, session, object, CKA_PUBLIC_EXPONENT); + + p11rsa = calloc(1, sizeof(*p11rsa)); + if (p11rsa == NULL) + _hx509_abort("out of memory"); + + p11rsa->p = p; + p11rsa->slot = slot; + p11rsa->private_key = object; + + if (p->ref == 0) + _hx509_abort("pkcs11 ref == 0 on alloc"); + p->ref++; + if (p->ref == UINT_MAX) + _hx509_abort("pkcs11 ref == UINT_MAX on alloc"); + + RSA_set_method(rsa, &p11_rsa_pkcs1_method); + ret = RSA_set_app_data(rsa, p11rsa); + if (ret != 1) + _hx509_abort("RSA_set_app_data"); + + hx509_private_key_assign_rsa(key, rsa); + + ret = _hx509_collector_private_key_add(context, + collector, + hx509_signature_rsa(), + key, + NULL, + &localKeyId); + + if (ret) { + hx509_private_key_free(&key); + return ret; + } + return 0; +} + +static void +p11_cert_release(hx509_cert cert, void *ctx) +{ + struct p11_module *p = ctx; + p11_release_module(p); +} + + +static int +collect_cert(hx509_context context, + struct p11_module *p, struct p11_slot *slot, + CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + void *ptr, CK_ATTRIBUTE *query, int num_query) +{ + struct hx509_collector *collector = ptr; + heim_error_t error = NULL; + hx509_cert cert; + int ret; + + if ((CK_LONG)query[0].ulValueLen == -1 || + (CK_LONG)query[1].ulValueLen == -1) + { + return 0; + } + + cert = hx509_cert_init_data(context, query[1].pValue, + query[1].ulValueLen, &error); + if (cert == NULL) { + ret = heim_error_get_code(error); + heim_release(error); + return ret; + } + + if (p->ref == 0) + _hx509_abort("pkcs11 ref == 0 on alloc"); + p->ref++; + if (p->ref == UINT_MAX) + _hx509_abort("pkcs11 ref to high"); + + _hx509_cert_set_release(cert, p11_cert_release, p); + + { + heim_octet_string data; + + data.data = query[0].pValue; + data.length = query[0].ulValueLen; + + _hx509_set_cert_attribute(context, + cert, + &asn1_oid_id_pkcs_9_at_localKeyId, + &data); + } + + if ((CK_LONG)query[2].ulValueLen != -1) { + char *str; + + ret = asprintf(&str, "%.*s", + (int)query[2].ulValueLen, (char *)query[2].pValue); + if (ret != -1 && str) { + hx509_cert_set_friendly_name(cert, str); + free(str); + } + } + + ret = _hx509_collector_certs_add(context, collector, cert); + hx509_cert_free(cert); + + return ret; +} + + +static int +p11_list_keys(hx509_context context, + struct p11_module *p, + struct p11_slot *slot, + CK_SESSION_HANDLE session, + hx509_lock lock, + hx509_certs *certs) +{ + struct hx509_collector *collector; + CK_OBJECT_CLASS key_class; + CK_ATTRIBUTE search_data[] = { + {CKA_CLASS, NULL, 0}, + }; + CK_ATTRIBUTE query_data[3] = { + {CKA_ID, NULL, 0}, + {CKA_VALUE, NULL, 0}, + {CKA_LABEL, NULL, 0} + }; + int ret; + + search_data[0].pValue = &key_class; + search_data[0].ulValueLen = sizeof(key_class); + + if (lock == NULL) + lock = _hx509_empty_lock; + + ret = _hx509_collector_alloc(context, lock, &collector); + if (ret) + return ret; + + key_class = CKO_PRIVATE_KEY; + ret = iterate_entries(context, p, slot, session, + search_data, 1, + query_data, 1, + collect_private_key, collector); + if (ret) + goto out; + + key_class = CKO_CERTIFICATE; + ret = iterate_entries(context, p, slot, session, + search_data, 1, + query_data, 3, + collect_cert, collector); + if (ret) + goto out; + + ret = _hx509_collector_collect_certs(context, collector, &slot->certs); + +out: + _hx509_collector_free(collector); + + return ret; +} + + +static int +p11_init(hx509_context context, + hx509_certs certs, void **data, int flags, + const char *residue, hx509_lock lock) +{ + CK_C_GetFunctionList getFuncs; + struct p11_module *p; + char *list, *str; + int ret; + + *data = NULL; + + if (flags & HX509_CERTS_NO_PRIVATE_KEYS) { + hx509_set_error_string(context, 0, ENOTSUP, + "PKCS#11 store does not support " + "HX509_CERTS_NO_PRIVATE_KEYS flag"); + return ENOTSUP; + } + + if (residue == NULL || residue[0] == '\0') { + hx509_set_error_string(context, 0, EINVAL, + "PKCS#11 store not specified"); + return EINVAL; + } + list = strdup(residue); + if (list == NULL) + return ENOMEM; + + p = calloc(1, sizeof(*p)); + if (p == NULL) { + free(list); + return ENOMEM; + } + + p->ref = 1; + p->selected_slot = 0; + + str = strchr(list, ','); + if (str) + *str++ = '\0'; + while (str) { + char *strnext; + strnext = strchr(str, ','); + if (strnext) + *strnext++ = '\0'; + if (strncasecmp(str, "slot=", 5) == 0) + p->selected_slot = atoi(str + 5); + str = strnext; + } + + p->dl_handle = dlopen(list, RTLD_NOW | RTLD_LOCAL | RTLD_GROUP); + if (p->dl_handle == NULL) { + ret = HX509_PKCS11_LOAD; + hx509_set_error_string(context, 0, ret, + "Failed to open %s: %s", list, dlerror()); + goto out; + } + + getFuncs = (CK_C_GetFunctionList) dlsym(p->dl_handle, "C_GetFunctionList"); + if (getFuncs == NULL) { + ret = HX509_PKCS11_LOAD; + hx509_set_error_string(context, 0, ret, + "C_GetFunctionList missing in %s: %s", + list, dlerror()); + goto out; + } + + ret = (*getFuncs)(&p->funcs); + if (ret) { + ret = HX509_PKCS11_LOAD; + hx509_set_error_string(context, 0, ret, + "C_GetFunctionList failed in %s", list); + goto out; + } + + ret = P11FUNC(p, Initialize, (NULL_PTR)); + if (ret != CKR_OK) { + ret = HX509_PKCS11_TOKEN_CONFUSED; + hx509_set_error_string(context, 0, ret, + "Failed initialize the PKCS11 module"); + goto out; + } + + ret = P11FUNC(p, GetSlotList, (FALSE, NULL, &p->num_slots)); + if (ret) { + ret = HX509_PKCS11_TOKEN_CONFUSED; + hx509_set_error_string(context, 0, ret, + "Failed to get number of PKCS11 slots"); + goto out; + } + + if (p->num_slots == 0) { + ret = HX509_PKCS11_NO_SLOT; + hx509_set_error_string(context, 0, ret, + "Selected PKCS11 module have no slots"); + goto out; + } + + + { + CK_SLOT_ID_PTR slot_ids; + int num_tokens = 0; + size_t i; + + slot_ids = malloc(p->num_slots * sizeof(*slot_ids)); + if (slot_ids == NULL) { + hx509_clear_error_string(context); + ret = ENOMEM; + goto out; + } + + ret = P11FUNC(p, GetSlotList, (FALSE, slot_ids, &p->num_slots)); + if (ret) { + free(slot_ids); + hx509_set_error_string(context, 0, HX509_PKCS11_TOKEN_CONFUSED, + "Failed getting slot-list from " + "PKCS11 module"); + ret = HX509_PKCS11_TOKEN_CONFUSED; + goto out; + } + + p->slot = calloc(p->num_slots, sizeof(p->slot[0])); + if (p->slot == NULL) { + free(slot_ids); + hx509_set_error_string(context, 0, ENOMEM, + "Failed to get memory for slot-list"); + ret = ENOMEM; + goto out; + } + + for (i = 0; i < p->num_slots; i++) { + if ((p->selected_slot != 0) && (slot_ids[i] != (p->selected_slot - 1))) + continue; + ret = p11_init_slot(context, p, lock, slot_ids[i], i, &p->slot[i]); + if (!ret) { + if (p->slot[i].flags & P11_TOKEN_PRESENT) + num_tokens++; + } + } + free(slot_ids); + if (ret) + goto out; + if (num_tokens == 0) { + ret = HX509_PKCS11_NO_TOKEN; + goto out; + } + } + + free(list); + + *data = p; + + return 0; + out: + if (list) + free(list); + p11_release_module(p); + return ret; +} + +static void +p11_release_module(struct p11_module *p) +{ + size_t i; + + if (p->ref == 0) + _hx509_abort("pkcs11 ref to low"); + if (--p->ref > 0) + return; + + for (i = 0; i < p->num_slots; i++) { + if (p->slot[i].flags & P11_SESSION_IN_USE) + _hx509_abort("pkcs11 module release while session in use"); + if (p->slot[i].flags & P11_SESSION) { + P11FUNC(p, CloseSession, (p->slot[i].session)); + } + + if (p->slot[i].name) + free(p->slot[i].name); + if (p->slot[i].pin) { + memset(p->slot[i].pin, 0, strlen(p->slot[i].pin)); + free(p->slot[i].pin); + } + if (p->slot[i].mechs.num) { + free(p->slot[i].mechs.list); + + if (p->slot[i].mechs.infos) { + size_t j; + + for (j = 0 ; j < p->slot[i].mechs.num ; j++) + free(p->slot[i].mechs.infos[j]); + free(p->slot[i].mechs.infos); + } + } + } + free(p->slot); + + if (p->funcs) + P11FUNC(p, Finalize, (NULL)); + + if (p->dl_handle) + dlclose(p->dl_handle); + + memset(p, 0, sizeof(*p)); + free(p); +} + +static int +p11_free(hx509_certs certs, void *data) +{ + struct p11_module *p = data; + size_t i; + + for (i = 0; i < p->num_slots; i++) { + if (p->slot[i].certs) + hx509_certs_free(&p->slot[i].certs); + } + p11_release_module(p); + return 0; +} + +struct p11_cursor { + hx509_certs certs; + void *cursor; +}; + +static int +p11_iter_start(hx509_context context, + hx509_certs certs, void *data, void **cursor) +{ + struct p11_module *p = data; + struct p11_cursor *c; + int ret; + size_t i; + + c = malloc(sizeof(*c)); + if (c == NULL) { + hx509_clear_error_string(context); + return ENOMEM; + } + ret = hx509_certs_init(context, "MEMORY:pkcs11-iter", 0, NULL, &c->certs); + if (ret) { + free(c); + return ret; + } + + for (i = 0 ; i < p->num_slots; i++) { + if (p->slot[i].certs == NULL) + continue; + ret = hx509_certs_merge(context, c->certs, p->slot[i].certs); + if (ret) { + hx509_certs_free(&c->certs); + free(c); + return ret; + } + } + + ret = hx509_certs_start_seq(context, c->certs, &c->cursor); + if (ret) { + hx509_certs_free(&c->certs); + free(c); + return 0; + } + *cursor = c; + + return 0; +} + +static int +p11_iter(hx509_context context, + hx509_certs certs, void *data, void *cursor, hx509_cert *cert) +{ + struct p11_cursor *c = cursor; + return hx509_certs_next_cert(context, c->certs, c->cursor, cert); +} + +static int +p11_iter_end(hx509_context context, + hx509_certs certs, void *data, void *cursor) +{ + struct p11_cursor *c = cursor; + int ret; + ret = hx509_certs_end_seq(context, c->certs, c->cursor); + hx509_certs_free(&c->certs); + free(c); + return ret; +} + +#define MECHFLAG(x) { "unknown-flag-" #x, x } +static struct units mechflags[] = { + MECHFLAG(0x80000000), + MECHFLAG(0x40000000), + MECHFLAG(0x20000000), + MECHFLAG(0x10000000), + MECHFLAG(0x08000000), + MECHFLAG(0x04000000), + {"ec-compress", 0x2000000 }, + {"ec-uncompress", 0x1000000 }, + {"ec-namedcurve", 0x0800000 }, + {"ec-ecparameters", 0x0400000 }, + {"ec-f-2m", 0x0200000 }, + {"ec-f-p", 0x0100000 }, + {"derive", 0x0080000 }, + {"unwrap", 0x0040000 }, + {"wrap", 0x0020000 }, + {"genereate-key-pair", 0x0010000 }, + {"generate", 0x0008000 }, + {"verify-recover", 0x0004000 }, + {"verify", 0x0002000 }, + {"sign-recover", 0x0001000 }, + {"sign", 0x0000800 }, + {"digest", 0x0000400 }, + {"decrypt", 0x0000200 }, + {"encrypt", 0x0000100 }, + MECHFLAG(0x00080), + MECHFLAG(0x00040), + MECHFLAG(0x00020), + MECHFLAG(0x00010), + MECHFLAG(0x00008), + MECHFLAG(0x00004), + MECHFLAG(0x00002), + {"hw", 0x0000001 }, + { NULL, 0x0000000 } +}; +#undef MECHFLAG + +static int +p11_printinfo(hx509_context context, + hx509_certs certs, + void *data, + int (*func)(void *, const char *), + void *ctx) +{ + struct p11_module *p = data; + size_t i, j; + + _hx509_pi_printf(func, ctx, "pkcs11 driver with %d slot%s", + p->num_slots, p->num_slots > 1 ? "s" : ""); + + for (i = 0; i < p->num_slots; i++) { + struct p11_slot *s = &p->slot[i]; + + _hx509_pi_printf(func, ctx, "slot %d: id: %d name: %s flags: %08x", + i, (int)s->id, s->name, s->flags); + + _hx509_pi_printf(func, ctx, "number of supported mechanisms: %lu", + (unsigned long)s->mechs.num); + for (j = 0; j < s->mechs.num; j++) { + const char *mechname = "unknown"; + char flags[256], unknownname[40]; +#define MECHNAME(s,n) case s: mechname = n; break + switch(s->mechs.list[j]) { + MECHNAME(CKM_RSA_PKCS_KEY_PAIR_GEN, "rsa-pkcs-key-pair-gen"); + MECHNAME(CKM_RSA_PKCS, "rsa-pkcs"); + MECHNAME(CKM_RSA_X_509, "rsa-x-509"); + MECHNAME(CKM_MD5_RSA_PKCS, "md5-rsa-pkcs"); + MECHNAME(CKM_SHA1_RSA_PKCS, "sha1-rsa-pkcs"); + MECHNAME(CKM_SHA256_RSA_PKCS, "sha256-rsa-pkcs"); + MECHNAME(CKM_SHA384_RSA_PKCS, "sha384-rsa-pkcs"); + MECHNAME(CKM_SHA512_RSA_PKCS, "sha512-rsa-pkcs"); + MECHNAME(CKM_RIPEMD160_RSA_PKCS, "ripemd160-rsa-pkcs"); + MECHNAME(CKM_RSA_PKCS_OAEP, "rsa-pkcs-oaep"); + MECHNAME(CKM_SHA512_HMAC, "sha512-hmac"); + MECHNAME(CKM_SHA512, "sha512"); + MECHNAME(CKM_SHA384_HMAC, "sha384-hmac"); + MECHNAME(CKM_SHA384, "sha384"); + MECHNAME(CKM_SHA256_HMAC, "sha256-hmac"); + MECHNAME(CKM_SHA256, "sha256"); + MECHNAME(CKM_SHA_1, "sha1"); + MECHNAME(CKM_MD5, "md5"); + MECHNAME(CKM_RIPEMD160, "ripemd-160"); + MECHNAME(CKM_DES_ECB, "des-ecb"); + MECHNAME(CKM_DES_CBC, "des-cbc"); + MECHNAME(CKM_AES_ECB, "aes-ecb"); + MECHNAME(CKM_AES_CBC, "aes-cbc"); + MECHNAME(CKM_DH_PKCS_PARAMETER_GEN, "dh-pkcs-parameter-gen"); + default: + snprintf(unknownname, sizeof(unknownname), + "unknown-mech-%lu", + (unsigned long)s->mechs.list[j]); + mechname = unknownname; + break; + } +#undef MECHNAME + unparse_flags(s->mechs.infos[j]->flags, mechflags, + flags, sizeof(flags)); + + _hx509_pi_printf(func, ctx, " %s: %s", mechname, flags); + } + } + + return 0; +} + +static struct hx509_keyset_ops keyset_pkcs11 = { + "PKCS11", + 0, + p11_init, + NULL, + p11_free, + NULL, + NULL, + p11_iter_start, + p11_iter, + p11_iter_end, + p11_printinfo, + NULL, + NULL, + NULL +}; + +#endif /* HAVE_DLOPEN */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_ks_pkcs11_register(hx509_context context) +{ +#ifdef HAVE_DLOPEN + _hx509_ks_register(context, &keyset_pkcs11); +#endif +} diff --git a/third_party/heimdal/lib/hx509/ks_p12.c b/third_party/heimdal/lib/hx509/ks_p12.c new file mode 100644 index 0000000..6fd7cd1 --- /dev/null +++ b/third_party/heimdal/lib/hx509/ks_p12.c @@ -0,0 +1,756 @@ +/* + * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" + +struct ks_pkcs12 { + hx509_certs certs; + char *fn; + unsigned int store_no_priv_keys; +}; + +typedef int (*collector_func)(hx509_context, + struct hx509_collector *, + int, + const void *, size_t, + const PKCS12_Attributes *); + +struct type { + const heim_oid *oid; + collector_func func; +}; + +static void +parse_pkcs12_type(hx509_context, struct hx509_collector *, int, + const heim_oid *, const void *, size_t, + const PKCS12_Attributes *); + + +static const PKCS12_Attribute * +find_attribute(const PKCS12_Attributes *attrs, const heim_oid *oid) +{ + size_t i; + if (attrs == NULL) + return NULL; + for (i = 0; i < attrs->len; i++) + if (der_heim_oid_cmp(oid, &attrs->val[i].attrId) == 0) + return &attrs->val[i]; + return NULL; +} + +static int +keyBag_parser(hx509_context context, + struct hx509_collector *c, + int flags, + const void *data, size_t length, + const PKCS12_Attributes *attrs) +{ + const PKCS12_Attribute *attr; + PKCS8PrivateKeyInfo ki; + const heim_octet_string *os = NULL; + int ret; + + if (flags & HX509_CERTS_NO_PRIVATE_KEYS) + return 0; + + attr = find_attribute(attrs, &asn1_oid_id_pkcs_9_at_localKeyId); + if (attr) + os = &attr->attrValues; + + ret = decode_PKCS8PrivateKeyInfo(data, length, &ki, NULL); + if (ret) + return ret; + + _hx509_collector_private_key_add(context, + c, + &ki.privateKeyAlgorithm, + NULL, + &ki.privateKey, + os); + free_PKCS8PrivateKeyInfo(&ki); + return 0; +} + +static int +ShroudedKeyBag_parser(hx509_context context, + struct hx509_collector *c, + int flags, + const void *data, size_t length, + const PKCS12_Attributes *attrs) +{ + PKCS8EncryptedPrivateKeyInfo pk; + heim_octet_string content; + int ret; + + memset(&pk, 0, sizeof(pk)); + + ret = decode_PKCS8EncryptedPrivateKeyInfo(data, length, &pk, NULL); + if (ret) + return ret; + + ret = _hx509_pbe_decrypt(context, + _hx509_collector_get_lock(c), + &pk.encryptionAlgorithm, + &pk.encryptedData, + &content); + free_PKCS8EncryptedPrivateKeyInfo(&pk); + if (ret) + return ret; + + ret = keyBag_parser(context, c, flags, content.data, content.length, + attrs); + der_free_octet_string(&content); + return ret; +} + +static int +certBag_parser(hx509_context context, + struct hx509_collector *c, + int flags, + const void *data, size_t length, + const PKCS12_Attributes *attrs) +{ + heim_error_t error = NULL; + heim_octet_string os; + hx509_cert cert; + PKCS12_CertBag cb; + int ret; + + ret = decode_PKCS12_CertBag(data, length, &cb, NULL); + if (ret) + return ret; + + if (der_heim_oid_cmp(&asn1_oid_id_pkcs_9_at_certTypes_x509, &cb.certType)) { + free_PKCS12_CertBag(&cb); + return 0; + } + + ret = decode_PKCS12_OctetString(cb.certValue.data, + cb.certValue.length, + &os, + NULL); + free_PKCS12_CertBag(&cb); + if (ret) + return ret; + + cert = hx509_cert_init_data(context, os.data, os.length, &error); + der_free_octet_string(&os); + if (cert == NULL) { + ret = heim_error_get_code(error); + heim_release(error); + return ret; + } + + ret = _hx509_collector_certs_add(context, c, cert); + if (ret) { + hx509_cert_free(cert); + return ret; + } + + { + const PKCS12_Attribute *attr; + const heim_oid *oids[] = { + &asn1_oid_id_pkcs_9_at_localKeyId, &asn1_oid_id_pkcs_9_at_friendlyName + }; + size_t i; + + for (i = 0; i < sizeof(oids)/sizeof(oids[0]); i++) { + const heim_oid *oid = oids[i]; + attr = find_attribute(attrs, oid); + if (attr) + _hx509_set_cert_attribute(context, cert, oid, + &attr->attrValues); + } + } + + hx509_cert_free(cert); + + return 0; +} + +static int +parse_safe_content(hx509_context context, + struct hx509_collector *c, + int flags, + const unsigned char *p, size_t len) +{ + PKCS12_SafeContents sc; + int ret; + size_t i; + + memset(&sc, 0, sizeof(sc)); + + ret = decode_PKCS12_SafeContents(p, len, &sc, NULL); + if (ret) + return ret; + + for (i = 0; i < sc.len ; i++) + parse_pkcs12_type(context, + c, + flags, + &sc.val[i].bagId, + sc.val[i].bagValue.data, + sc.val[i].bagValue.length, + sc.val[i].bagAttributes); + + free_PKCS12_SafeContents(&sc); + return 0; +} + +static int +safeContent_parser(hx509_context context, + struct hx509_collector *c, + int flags, + const void *data, size_t length, + const PKCS12_Attributes *attrs) +{ + heim_octet_string os; + int ret; + + ret = decode_PKCS12_OctetString(data, length, &os, NULL); + if (ret) + return ret; + ret = parse_safe_content(context, c, flags, os.data, os.length); + der_free_octet_string(&os); + return ret; +} + +static int +encryptedData_parser(hx509_context context, + struct hx509_collector *c, + int flags, + const void *data, size_t length, + const PKCS12_Attributes *attrs) +{ + heim_octet_string content; + heim_oid contentType; + int ret; + + memset(&contentType, 0, sizeof(contentType)); + + ret = hx509_cms_decrypt_encrypted(context, + _hx509_collector_get_lock(c), + data, length, + &contentType, + &content); + if (ret) + return ret; + + if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) == 0) + ret = parse_safe_content(context, c, flags, + content.data, content.length); + + der_free_octet_string(&content); + der_free_oid(&contentType); + return ret; +} + +static int +envelopedData_parser(hx509_context context, + struct hx509_collector *c, + int flags, + const void *data, size_t length, + const PKCS12_Attributes *attrs) +{ + heim_octet_string content; + heim_oid contentType; + hx509_lock lock; + int ret; + + memset(&contentType, 0, sizeof(contentType)); + + lock = _hx509_collector_get_lock(c); + + ret = hx509_cms_unenvelope(context, + _hx509_lock_unlock_certs(lock), + 0, + data, length, + NULL, + 0, + &contentType, + &content); + if (ret) { + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + "PKCS12 failed to unenvelope"); + return ret; + } + + if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) == 0) + ret = parse_safe_content(context, c, flags, + content.data, content.length); + + der_free_octet_string(&content); + der_free_oid(&contentType); + + return ret; +} + + +struct type bagtypes[] = { + { &asn1_oid_id_pkcs12_keyBag, keyBag_parser }, + { &asn1_oid_id_pkcs12_pkcs8ShroudedKeyBag, ShroudedKeyBag_parser }, + { &asn1_oid_id_pkcs12_certBag, certBag_parser }, + { &asn1_oid_id_pkcs7_data, safeContent_parser }, + { &asn1_oid_id_pkcs7_encryptedData, encryptedData_parser }, + { &asn1_oid_id_pkcs7_envelopedData, envelopedData_parser } +}; + +static void +parse_pkcs12_type(hx509_context context, + struct hx509_collector *c, + int flags, + const heim_oid *oid, + const void *data, size_t length, + const PKCS12_Attributes *attrs) +{ + size_t i; + + for (i = 0; i < sizeof(bagtypes)/sizeof(bagtypes[0]); i++) + if (der_heim_oid_cmp(bagtypes[i].oid, oid) == 0) + (*bagtypes[i].func)(context, c, flags, data, length, attrs); +} + +static int +p12_init(hx509_context context, + hx509_certs certs, void **data, int flags, + const char *residue, hx509_lock lock) +{ + struct ks_pkcs12 *p12; + size_t len; + void *buf; + PKCS12_PFX pfx; + PKCS12_AuthenticatedSafe as; + int ret; + size_t i; + struct hx509_collector *c; + + *data = NULL; + + if (residue == NULL || residue[0] == '\0') { + hx509_set_error_string(context, 0, EINVAL, + "PKCS#12 file not specified"); + return EINVAL; + } + + if (lock == NULL) + lock = _hx509_empty_lock; + + ret = _hx509_collector_alloc(context, lock, &c); + if (ret) + return ret; + + p12 = calloc(1, sizeof(*p12)); + if (p12 == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "out of memory"); + goto out; + } + + p12->fn = strdup(residue); + if (p12->fn == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "out of memory"); + goto out; + } + + if (flags & HX509_CERTS_CREATE) { + ret = hx509_certs_init(context, "MEMORY:ks-file-create", + 0, lock, &p12->certs); + if (ret == 0) + *data = p12; + goto out; + } + + ret = rk_undumpdata(residue, &buf, &len); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + + ret = decode_PKCS12_PFX(buf, len, &pfx, NULL); + rk_xfree(buf); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to decode the PFX in %s", residue); + goto out; + } + + if (der_heim_oid_cmp(&pfx.authSafe.contentType, &asn1_oid_id_pkcs7_data) != 0) { + free_PKCS12_PFX(&pfx); + ret = EINVAL; + hx509_set_error_string(context, 0, ret, + "PKCS PFX isn't a pkcs7-data container"); + goto out; + } + + if (pfx.authSafe.content == NULL) { + free_PKCS12_PFX(&pfx); + ret = EINVAL; + hx509_set_error_string(context, 0, ret, + "PKCS PFX missing data"); + goto out; + } + + { + heim_octet_string asdata; + + ret = decode_PKCS12_OctetString(pfx.authSafe.content->data, + pfx.authSafe.content->length, + &asdata, + NULL); + free_PKCS12_PFX(&pfx); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + ret = decode_PKCS12_AuthenticatedSafe(asdata.data, + asdata.length, + &as, + NULL); + der_free_octet_string(&asdata); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + } + + for (i = 0; i < as.len; i++) + parse_pkcs12_type(context, + c, + flags, + &as.val[i].contentType, + as.val[i].content->data, + as.val[i].content->length, + NULL); + + free_PKCS12_AuthenticatedSafe(&as); + + ret = _hx509_collector_collect_certs(context, c, &p12->certs); + if (ret == 0) + *data = p12; + +out: + _hx509_collector_free(c); + + if (ret && p12) { + if (p12->fn) + free(p12->fn); + if (p12->certs) + hx509_certs_free(&p12->certs); + free(p12); + } + + return ret; +} + +static int +addBag(hx509_context context, + PKCS12_AuthenticatedSafe *as, + const heim_oid *oid, + void *data, + size_t length) +{ + void *ptr; + int ret; + + ptr = realloc(as->val, sizeof(as->val[0]) * (as->len + 1)); + if (ptr == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + as->val = ptr; + + ret = der_copy_oid(oid, &as->val[as->len].contentType); + if (ret) { + hx509_set_error_string(context, 0, ret, "out of memory"); + return ret; + } + + as->val[as->len].content = calloc(1, sizeof(*as->val[0].content)); + if (as->val[as->len].content == NULL) { + der_free_oid(&as->val[as->len].contentType); + hx509_set_error_string(context, 0, ENOMEM, "malloc out of memory"); + return ENOMEM; + } + + as->val[as->len].content->data = data; + as->val[as->len].content->length = length; + + as->len++; + + return 0; +} + +struct store_func_ctx { + PKCS12_AuthenticatedSafe as; + int store_flags; +}; + +static int HX509_LIB_CALL +store_func(hx509_context context, void *d, hx509_cert c) +{ + struct store_func_ctx *ctx = d; + PKCS12_OctetString os; + PKCS12_CertBag cb; + size_t size; + int ret; + + memset(&os, 0, sizeof(os)); + memset(&cb, 0, sizeof(cb)); + + os.data = NULL; + os.length = 0; + + ret = hx509_cert_binary(context, c, &os); + if (ret) + return ret; + + ASN1_MALLOC_ENCODE(PKCS12_OctetString, + cb.certValue.data,cb.certValue.length, + &os, &size, ret); + free(os.data); + if (ret) + goto out; + ret = der_copy_oid(&asn1_oid_id_pkcs_9_at_certTypes_x509, &cb.certType); + if (ret) { + free_PKCS12_CertBag(&cb); + goto out; + } + ASN1_MALLOC_ENCODE(PKCS12_CertBag, os.data, os.length, + &cb, &size, ret); + free_PKCS12_CertBag(&cb); + if (ret) + goto out; + + ret = addBag(context, &ctx->as, &asn1_oid_id_pkcs12_certBag, os.data, + os.length); + + if (_hx509_cert_private_key_exportable(c) && + !(ctx->store_flags & HX509_CERTS_STORE_NO_PRIVATE_KEYS)) { + hx509_private_key key = _hx509_cert_private_key(c); + PKCS8PrivateKeyInfo pki; + + memset(&pki, 0, sizeof(pki)); + + ret = der_parse_hex_heim_integer("00", &pki.version); + if (ret) + return ret; + ret = _hx509_private_key_oid(context, key, + &pki.privateKeyAlgorithm.algorithm); + if (ret) { + free_PKCS8PrivateKeyInfo(&pki); + return ret; + } + ret = _hx509_private_key_export(context, + _hx509_cert_private_key(c), + HX509_KEY_FORMAT_DER, + &pki.privateKey); + if (ret) { + free_PKCS8PrivateKeyInfo(&pki); + return ret; + } + /* set attribute, asn1_oid_id_pkcs_9_at_localKeyId */ + + ASN1_MALLOC_ENCODE(PKCS8PrivateKeyInfo, os.data, os.length, + &pki, &size, ret); + free_PKCS8PrivateKeyInfo(&pki); + if (ret) + return ret; + + ret = addBag(context, &ctx->as, &asn1_oid_id_pkcs12_keyBag, os.data, + os.length); + if (ret) + return ret; + } + +out: + return ret; +} + +static int +p12_store(hx509_context context, + hx509_certs certs, void *data, int flags, hx509_lock lock) +{ + struct ks_pkcs12 *p12 = data; + PKCS12_PFX pfx; + struct store_func_ctx ctx; + PKCS12_OctetString asdata; + size_t size; + int ret; + + memset(&ctx, 0, sizeof(ctx)); + memset(&pfx, 0, sizeof(pfx)); + ctx.store_flags = flags; + + ret = hx509_certs_iter_f(context, p12->certs, store_func, &ctx); + if (ret) + goto out; + + ASN1_MALLOC_ENCODE(PKCS12_AuthenticatedSafe, asdata.data, asdata.length, + &ctx.as, &size, ret); + free_PKCS12_AuthenticatedSafe(&ctx.as); + if (ret) + return ret; + + ret = der_parse_hex_heim_integer("03", &pfx.version); + if (ret) { + free(asdata.data); + goto out; + } + + pfx.authSafe.content = calloc(1, sizeof(*pfx.authSafe.content)); + + ASN1_MALLOC_ENCODE(PKCS12_OctetString, + pfx.authSafe.content->data, + pfx.authSafe.content->length, + &asdata, &size, ret); + free(asdata.data); + if (ret) + goto out; + + ret = der_copy_oid(&asn1_oid_id_pkcs7_data, &pfx.authSafe.contentType); + if (ret) + goto out; + + ASN1_MALLOC_ENCODE(PKCS12_PFX, asdata.data, asdata.length, + &pfx, &size, ret); + if (ret) + goto out; + +#if 0 + const struct _hx509_password *pw; + + pw = _hx509_lock_get_passwords(lock); + if (pw != NULL) { + pfx.macData = calloc(1, sizeof(*pfx.macData)); + if (pfx.macData == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "malloc out of memory"); + return ret; + } + if (pfx.macData == NULL) { + free(asdata.data); + goto out; + } + } + ret = calculate_hash(&aspath, pw, pfx.macData); +#endif + + rk_dumpdata(p12->fn, asdata.data, asdata.length); + free(asdata.data); + +out: + free_PKCS12_AuthenticatedSafe(&ctx.as); + free_PKCS12_PFX(&pfx); + + return ret; +} + + +static int +p12_free(hx509_certs certs, void *data) +{ + struct ks_pkcs12 *p12 = data; + hx509_certs_free(&p12->certs); + free(p12->fn); + free(p12); + return 0; +} + +static int +p12_add(hx509_context context, hx509_certs certs, void *data, hx509_cert c) +{ + struct ks_pkcs12 *p12 = data; + return hx509_certs_add(context, p12->certs, c); +} + +static int +p12_iter_start(hx509_context context, + hx509_certs certs, + void *data, + void **cursor) +{ + struct ks_pkcs12 *p12 = data; + return hx509_certs_start_seq(context, p12->certs, cursor); +} + +static int +p12_iter(hx509_context context, + hx509_certs certs, + void *data, + void *cursor, + hx509_cert *cert) +{ + struct ks_pkcs12 *p12 = data; + return hx509_certs_next_cert(context, p12->certs, cursor, cert); +} + +static int +p12_iter_end(hx509_context context, + hx509_certs certs, + void *data, + void *cursor) +{ + struct ks_pkcs12 *p12 = data; + return hx509_certs_end_seq(context, p12->certs, cursor); +} + +static int +p12_destroy(hx509_context context, hx509_certs certs, void *data) +{ + struct ks_pkcs12 *p12 = data; + return _hx509_erase_file(context, p12->fn); +} + +static struct hx509_keyset_ops keyset_pkcs12 = { + "PKCS12", + 0, + p12_init, + p12_store, + p12_free, + p12_add, + NULL, + p12_iter_start, + p12_iter, + p12_iter_end, + NULL, + NULL, + NULL, + p12_destroy +}; + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_ks_pkcs12_register(hx509_context context) +{ + _hx509_ks_register(context, &keyset_pkcs12); +} diff --git a/third_party/heimdal/lib/hx509/libhx509-exports.def b/third_party/heimdal/lib/hx509/libhx509-exports.def new file mode 100644 index 0000000..745ad5a --- /dev/null +++ b/third_party/heimdal/lib/hx509/libhx509-exports.def @@ -0,0 +1,288 @@ + +EXPORTS + _hx509_cert_assign_key + _hx509_cert_get_keyusage + _hx509_cert_get_version + _hx509_cert_private_key + _hx509_certs_keys_free + _hx509_certs_keys_get + _hx509_expr_eval + _hx509_expr_free + _hx509_expr_parse + _hx509_generate_private_key + _hx509_generate_private_key_bits + _hx509_generate_private_key_free + _hx509_generate_private_key_init + _hx509_generate_private_key_is_ca + _hx509_get_cert + _hx509_ks_type + _hx509_make_pkinit_san + _hx509_map_file_os + _hx509_name_from_Name + hx509_private_key2SPKI + hx509_private_key_free + _hx509_private_key_ref + hx509_request_add_GeneralName + hx509_request_add_dns_name + hx509_request_add_dns_srv + hx509_request_add_eku + hx509_request_add_email + hx509_request_add_ms_upn_name + hx509_request_add_pkinit + hx509_request_add_registered + hx509_request_add_xmpp_name + hx509_request_authorize_ku + hx509_request_authorize_eku + hx509_request_authorize_san + hx509_request_count_unsupported + hx509_request_count_unauthorized + _hx509_private_key_export + _hx509_private_key_exportable + _hx509_private_key_get_internal + _hx509_private_key_oid + _hx509_private_key_ref + hx509_request_free + hx509_request_get_eku + hx509_request_get_exts + hx509_request_get_ku + hx509_request_get_name + hx509_request_get_san + hx509_request_get_SubjectPublicKeyInfo + hx509_request_get_name + hx509_request_init + hx509_request_parse + hx509_request_parse_der + hx509_request_print + hx509_request_set_SubjectPublicKeyInfo + hx509_request_add_email + hx509_request_set_name + hx509_request_set_ku + hx509_request_to_pkcs10 + _hx509_unmap_file_os + _hx509_write_file + hx509_bitstring_print + _hx509_ca_issue_certificate + hx509_ca_sign + hx509_ca_sign_self + hx509_ca_tbs_add_crl_dp_uri + hx509_ca_tbs_add_eku + hx509_ca_tbs_add_ku + hx509_ca_tbs_add_pol + hx509_ca_tbs_add_pol_mapping + hx509_ca_tbs_add_san + hx509_ca_tbs_add_san_dnssrv + hx509_ca_tbs_add_san_hardwareModuleName + hx509_ca_tbs_add_san_hardwareModuleName_string + hx509_ca_tbs_add_san_hostname + hx509_ca_tbs_add_san_jid + hx509_ca_tbs_add_san_ms_upn + hx509_ca_tbs_add_san_otherName + hx509_ca_tbs_add_san_permanentIdentifier + hx509_ca_tbs_add_san_permanentIdentifier_string + hx509_ca_tbs_add_san_pkinit + hx509_ca_tbs_add_san_rfc822name + hx509_ca_tbs_free + hx509_ca_tbs_get_name + hx509_ca_tbs_init + hx509_ca_tbs_set_ca + hx509_ca_tbs_set_domaincontroller + hx509_ca_tbs_set_from_csr + hx509_ca_tbs_set_notAfter + hx509_ca_tbs_set_notAfter_lifetime + hx509_ca_tbs_set_notBefore + hx509_ca_tbs_set_pkinit_max_life + hx509_ca_tbs_set_proxy + hx509_ca_tbs_set_serialnumber + hx509_ca_tbs_set_signature_algorithm + hx509_ca_tbs_set_spki + hx509_ca_tbs_set_subject + hx509_ca_tbs_set_template + hx509_ca_tbs_subject_expand + hx509_ca_tbs_template_units +; hx509_cert +; hx509_cert_attribute + hx509_cert_binary + hx509_cert_check_eku + hx509_cert_cmp + hx509_cert_find_subjectAltName_otherName + hx509_cert_free + hx509_cert_get_SPKI + hx509_cert_get_SPKI_AlgorithmIdentifier + hx509_cert_get_attribute + hx509_cert_get_base_subject + hx509_cert_get_friendly_name + hx509_cert_get_issuer + hx509_cert_get_notAfter + hx509_cert_get_notBefore + hx509_cert_get_pkinit_max_life + hx509_cert_get_serialnumber + hx509_cert_get_subject + hx509_cert_have_private_key + hx509_cert_have_private_key_only + hx509_cert_init + hx509_cert_init_data + hx509_cert_init_private_key + hx509_cert_keyusage_print + hx509_cert_ref + hx509_cert_set_friendly_name + hx509_certs_add + hx509_certs_append + hx509_certs_destroy + hx509_certs_end_seq + hx509_certs_ref + hx509_certs_filter + hx509_certs_find + hx509_certs_free + hx509_certs_info + hx509_certs_init +; hx509_certs_iter + hx509_certs_iter_f + hx509_certs_merge + hx509_certs_next_cert + hx509_certs_start_seq + hx509_certs_store + hx509_ci_print_names + hx509_clear_error_string + hx509_cms_create_signed + hx509_cms_create_signed_1 + hx509_cms_decrypt_encrypted + hx509_cms_envelope_1 + hx509_cms_unenvelope + hx509_cms_unwrap_ContentInfo + hx509_cms_verify_signed + hx509_cms_verify_signed_ext + hx509_cms_wrap_ContentInfo + hx509_context_free + hx509_context_init + hx509_context_set_missing_revoke + hx509_crl_add_revoked_certs + hx509_crl_alloc + hx509_crl_free + hx509_crl_lifetime + hx509_crl_sign + hx509_crypto_aes128_cbc + hx509_crypto_aes256_cbc + hx509_crypto_allow_weak + hx509_crypto_available + hx509_crypto_decrypt + hx509_crypto_des_rsdi_ede3_cbc + hx509_crypto_destroy + hx509_crypto_encrypt + hx509_crypto_enctype_by_name + hx509_crypto_free_algs + hx509_crypto_get_params + hx509_crypto_init + hx509_crypto_provider + hx509_crypto_select + hx509_crypto_set_key_data + hx509_crypto_set_key_name + hx509_crypto_set_padding + hx509_crypto_set_params + hx509_crypto_set_random_key + hx509_empty_name + hx509_env_add + hx509_env_add_binding + hx509_env_find + hx509_env_find_binding + hx509_env_free +; hx509_env_init + hx509_env_lfind + hx509_err + hx509_free_error_string + hx509_free_octet_string_list + hx509_general_name_unparse + hx509_get_error_string + hx509_get_instance + hx509_get_one_cert + hx509_lock_add_cert + hx509_lock_add_certs + hx509_lock_add_password + hx509_lock_command_string + hx509_lock_free + hx509_lock_init + hx509_lock_prompt + hx509_lock_reset_certs + hx509_lock_reset_passwords + hx509_lock_reset_promper + hx509_lock_set_prompter + hx509_name_binary + hx509_name_cmp + hx509_name_copy + hx509_name_expand + hx509_name_free + hx509_name_is_null_p + hx509_name_normalize + hx509_name_to_Name + hx509_name_to_string + hx509_ocsp_request + hx509_ocsp_verify + hx509_oid_print + hx509_oid_sprint + hx509_parse_name + hx509_parse_private_key + hx509_peer_info_add_cms_alg + hx509_peer_info_alloc + hx509_peer_info_free + hx509_peer_info_set_cert + hx509_peer_info_set_cms_algs + hx509_pem_add_header + hx509_pem_find_header + hx509_pem_free_header + hx509_pem_read + hx509_pem_write + hx509_print_stdout + hx509_print_cert + hx509_prompt_hidden + hx509_query_alloc + hx509_query_free + hx509_query_match_cmp_func + hx509_query_match_eku + hx509_query_match_expr + hx509_query_match_friendly_name + hx509_query_match_issuer_serial + hx509_query_match_option + hx509_query_statistic_file + hx509_query_unparse_stats + hx509_revoke_add_crl + hx509_revoke_add_ocsp + hx509_revoke_free + hx509_revoke_init + hx509_revoke_ocsp_print + hx509_revoke_print + hx509_revoke_verify + hx509_set_error_string + hx509_set_error_stringv + hx509_signature_md5 + hx509_signature_rsa + hx509_signature_rsa_with_md5 + hx509_signature_rsa_with_sha1 + hx509_signature_rsa_with_sha256 + hx509_signature_rsa_with_sha384 + hx509_signature_rsa_with_sha512 + hx509_signature_sha1 + hx509_signature_sha256 + hx509_signature_sha384 + hx509_signature_sha512 + hx509_unparse_der_name + hx509_validate_cert + hx509_validate_ctx_add_flags + hx509_validate_ctx_free + hx509_validate_ctx_init + hx509_validate_ctx_set_print + hx509_verify_attach_anchors + hx509_verify_attach_revoke + hx509_verify_ctx_f_allow_default_trustanchors + hx509_verify_destroy_ctx + hx509_verify_hostname + hx509_verify_init_ctx + hx509_verify_path + hx509_verify_set_max_depth + hx509_verify_set_proxy_certificate + hx509_verify_set_strict_rfc3280_verification + hx509_verify_set_time + hx509_verify_signature + hx509_xfree + initialize_hx_error_table_r + +; pkcs11 symbols + C_GetFunctionList diff --git a/third_party/heimdal/lib/hx509/lock.c b/third_party/heimdal/lib/hx509/lock.c new file mode 100644 index 0000000..7f767d2 --- /dev/null +++ b/third_party/heimdal/lib/hx509/lock.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2005 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" + +/** + * @page page_lock Locking and unlocking certificates and encrypted data. + * + * See the library functions here: @ref hx509_lock + */ + +struct hx509_lock_data { + struct _hx509_password password; + hx509_certs certs; + hx509_prompter_fct prompt; + void *prompt_data; +}; + +static struct hx509_lock_data empty_lock_data = { + { 0, NULL }, + NULL, + NULL, + NULL +}; + +hx509_lock _hx509_empty_lock = &empty_lock_data; + +/* + * + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_lock_init(hx509_context context, hx509_lock *lock) +{ + hx509_lock l; + int ret; + + *lock = NULL; + + l = calloc(1, sizeof(*l)); + if (l == NULL) + return ENOMEM; + + ret = hx509_certs_init(context, + "MEMORY:locks-internal", + 0, + NULL, + &l->certs); + if (ret) { + free(l); + return ret; + } + + *lock = l; + + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_lock_add_password(hx509_lock lock, const char *password) +{ + void *d; + char *s; + + s = strdup(password); + if (s == NULL) + return ENOMEM; + + d = realloc(lock->password.val, + (lock->password.len + 1) * sizeof(lock->password.val[0])); + if (d == NULL) { + free(s); + return ENOMEM; + } + lock->password.val = d; + lock->password.val[lock->password.len] = s; + lock->password.len++; + + return 0; +} + +HX509_LIB_FUNCTION const struct _hx509_password * HX509_LIB_CALL +_hx509_lock_get_passwords(hx509_lock lock) +{ + return &lock->password; +} + +HX509_LIB_FUNCTION hx509_certs HX509_LIB_CALL +_hx509_lock_unlock_certs(hx509_lock lock) +{ + return lock->certs; +} + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_lock_reset_passwords(hx509_lock lock) +{ + size_t i; + for (i = 0; i < lock->password.len; i++) + free(lock->password.val[i]); + free(lock->password.val); + lock->password.val = NULL; + lock->password.len = 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_lock_add_cert(hx509_context context, hx509_lock lock, hx509_cert cert) +{ + return hx509_certs_add(context, lock->certs, cert); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_lock_add_certs(hx509_context context, hx509_lock lock, hx509_certs certs) +{ + return hx509_certs_merge(context, lock->certs, certs); +} + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_lock_reset_certs(hx509_context context, hx509_lock lock) +{ + hx509_certs certs = lock->certs; + int ret; + + ret = hx509_certs_init(context, + "MEMORY:locks-internal", + 0, + NULL, + &lock->certs); + if (ret == 0) + hx509_certs_free(&certs); + else + lock->certs = certs; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_lock_find_cert(hx509_lock lock, const hx509_query *q, hx509_cert *c) +{ + *c = NULL; + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_lock_set_prompter(hx509_lock lock, hx509_prompter_fct prompt, void *data) +{ + lock->prompt = prompt; + lock->prompt_data = data; + return 0; +} + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_lock_reset_promper(hx509_lock lock) +{ + lock->prompt = NULL; + lock->prompt_data = NULL; +} + +static int +default_prompter(void *data, const hx509_prompt *prompter) +{ + if (hx509_prompt_hidden(prompter->type)) { + if(UI_UTIL_read_pw_string(prompter->reply.data, + prompter->reply.length, + prompter->prompt, + 0)) + return 1; + } else { + char *s = prompter->reply.data; + + fputs (prompter->prompt, stdout); + fflush (stdout); + if(fgets(prompter->reply.data, + prompter->reply.length, + stdin) == NULL) + return 1; + s[strcspn(s, "\n")] = '\0'; + } + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_lock_prompt(hx509_lock lock, hx509_prompt *prompt) +{ + if (lock->prompt == NULL) + return HX509_CRYPTO_NO_PROMPTER; + return (*lock->prompt)(lock->prompt_data, prompt); +} + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_lock_free(hx509_lock lock) +{ + if (lock) { + hx509_certs_free(&lock->certs); + hx509_lock_reset_passwords(lock); + memset(lock, 0, sizeof(*lock)); + free(lock); + } +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_prompt_hidden(hx509_prompt_type type) +{ + /* default to hidden if unknown */ + + switch (type) { + case HX509_PROMPT_TYPE_QUESTION: + case HX509_PROMPT_TYPE_INFO: + return 0; + default: + return 1; + } +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_lock_command_string(hx509_lock lock, const char *string) +{ + if (strncasecmp(string, "PASS:", 5) == 0) { + hx509_lock_add_password(lock, string + 5); + } else if (strcasecmp(string, "PROMPT") == 0) { + hx509_lock_set_prompter(lock, default_prompter, NULL); + } else + return HX509_UNKNOWN_LOCK_COMMAND; + return 0; +} diff --git a/third_party/heimdal/lib/hx509/name.c b/third_party/heimdal/lib/hx509/name.c new file mode 100644 index 0000000..7d67716 --- /dev/null +++ b/third_party/heimdal/lib/hx509/name.c @@ -0,0 +1,1529 @@ +/* + * Copyright (c) 2004 - 2009 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" +#include <wind.h> +#include "char_map.h" + +/** + * @page page_name PKIX/X.509 Names + * + * There are several names in PKIX/X.509, GeneralName and Name. + * + * A Name consists of an ordered list of Relative Distinguished Names + * (RDN). Each RDN consists of an unordered list of typed strings. The + * types are defined by OID and have long and short description. For + * example id-at-commonName (2.5.4.3) have the long name CommonName + * and short name CN. The string itself can be of several encoding, + * UTF8, UTF16, Teltex string, etc. The type limit what encoding + * should be used. + * + * GeneralName is a broader nametype that can contains al kind of + * stuff like Name, IP addresses, partial Name, etc. + * + * Name is mapped into a hx509_name object. + * + * Parse and string name into a hx509_name object with hx509_parse_name(), + * make it back into string representation with hx509_name_to_string(). + * + * Name string are defined rfc2253, rfc1779 and X.501. + * + * See the library functions here: @ref hx509_name + */ + +static const struct { + const char *n; + const heim_oid *o; + int type_choice; /* Preference for DirectoryString choice; 0 -> no pref */ + wind_profile_flags flags; + /* + * RFC52380 imposes maximum lengths for some strings in Names. These are + * ASN.1 size limits. We should implement these in our copy of the PKIX + * ASN.1 module. For now we treat them as maximum byte counts rather than + * maximum character counts, and we encode and enforce them here. + * + * 0 -> no max + * + * Some of these attributes aren't of type DirectoryString, so our + * type_choice isn't really correct. We're not really set up for + * attributes whose types aren't DirectoryString or one of its choice arms' + * type, much less are we set up for non-string attribute value types. + */ + size_t max_bytes; +} no[] = { + { "C", &asn1_oid_id_at_countryName, + choice_DirectoryString_printableString, 0, 2 }, + { "CN", &asn1_oid_id_at_commonName, 0, 0, ub_common_name }, + { "DC", &asn1_oid_id_domainComponent, choice_DirectoryString_ia5String, + 0, 63 }, /* DNS label */ + { "L", &asn1_oid_id_at_localityName, 0, 0, ub_locality_name }, + { "O", &asn1_oid_id_at_organizationName, 0, 0, ub_organization_name }, + { "OU", &asn1_oid_id_at_organizationalUnitName, 0, 0, + ub_organizational_unit_name }, + { "S", &asn1_oid_id_at_stateOrProvinceName, 0, 0, ub_state_name }, + { "STREET", &asn1_oid_id_at_streetAddress, 0, 0, 0 }, /* ENOTSUP */ + { "UID", &asn1_oid_id_Userid, 0, 0, ub_numeric_user_id_length }, + { "emailAddress", &asn1_oid_id_pkcs9_emailAddress, + choice_DirectoryString_ia5String, 0, ub_emailaddress_length }, + /* This is for DevID certificates and maybe others */ + { "serialNumber", &asn1_oid_id_at_serialNumber, 0, 0, ub_serial_number }, + /* These are for TPM 2.0 Endorsement Key Certificates (EKCerts) */ + { "TPMManufacturer", &asn1_oid_tcg_at_tpmManufacturer, 0, 0, + ub_emailaddress_length }, + { "TPMModel", &asn1_oid_tcg_at_tpmModel, 0, 0, ub_emailaddress_length }, + { "TPMVersion", &asn1_oid_tcg_at_tpmVersion, 0, 0, ub_emailaddress_length }, +}; + +static char * +quote_string(const char *f, size_t len, int flags, size_t *rlen) +{ + size_t i, j, tolen; + const unsigned char *from = (const unsigned char *)f; + unsigned char *to; + + tolen = len * 3 + 1; + to = malloc(tolen); + if (to == NULL) + return NULL; + + for (i = 0, j = 0; i < len; i++) { + unsigned char map = char_map[from[i]] & flags; + if (i == 0 && (map & Q_RFC2253_QUOTE_FIRST)) { + to[j++] = '\\'; + to[j++] = from[i]; + } else if ((i + 1) == len && (map & Q_RFC2253_QUOTE_LAST)) { + + to[j++] = '\\'; + to[j++] = from[i]; + } else if (map & Q_RFC2253_QUOTE) { + to[j++] = '\\'; + to[j++] = from[i]; + } else if (map & Q_RFC2253_HEX) { + int l = snprintf((char *)&to[j], tolen - j - 1, + "#%02x", (unsigned char)from[i]); + j += l; + } else { + to[j++] = from[i]; + } + } + to[j] = '\0'; + assert(j < tolen); + *rlen = j; + return (char *)to; +} + + +static int +append_string(char **str, size_t *total_len, const char *ss, + size_t len, int quote) +{ + char *s, *qs; + + if (quote) + qs = quote_string(ss, len, Q_RFC2253, &len); + else + qs = rk_UNCONST(ss); + + s = realloc(*str, len + *total_len + 1); + if (s == NULL) + _hx509_abort("allocation failure"); /* XXX */ + memcpy(s + *total_len, qs, len); + if (qs != ss) + free(qs); + s[*total_len + len] = '\0'; + *str = s; + *total_len += len; + return 0; +} + +static char * +oidtostring(const heim_oid *type, int *type_choice) +{ + char *s; + size_t i; + + if (type_choice) + *type_choice = choice_DirectoryString_utf8String; + + for (i = 0; i < sizeof(no)/sizeof(no[0]); i++) { + if (der_heim_oid_cmp(no[i].o, type) == 0) { + if (type_choice && no[i].type_choice) + *type_choice = no[i].type_choice; + return strdup(no[i].n); + } + } + if (der_print_heim_oid(type, '.', &s) != 0) + return NULL; + return s; +} + +static size_t +oidtomaxlen(const heim_oid *type) +{ + size_t i; + + for (i = 0; i < sizeof(no)/sizeof(no[0]); i++) { + if (der_heim_oid_cmp(no[i].o, type) == 0) + return no[i].max_bytes; + } + return 0; +} + +static int +stringtooid(const char *name, size_t len, heim_oid *oid) +{ + int ret; + size_t i; + char *s; + + memset(oid, 0, sizeof(*oid)); + + for (i = 0; i < sizeof(no)/sizeof(no[0]); i++) { + if (strncasecmp(no[i].n, name, len) == 0) + return der_copy_oid(no[i].o, oid); + } + s = malloc(len + 1); + if (s == NULL) + return ENOMEM; + memcpy(s, name, len); + s[len] = '\0'; + ret = der_parse_heim_oid(s, ".", oid); + free(s); + return ret; +} + +/** + * Convert the hx509 name object into a printable string. + * The resulting string should be freed with free(). + * + * @param name name to print + * @param str the string to return + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_name + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_name_to_string(const hx509_name name, char **str) +{ + return _hx509_Name_to_string(&name->der_name, str); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_Name_to_string(const Name *n, char **str) +{ + size_t total_len = 0; + size_t i, j, m; + int ret; + + *str = strdup(""); + if (*str == NULL) + return ENOMEM; + + for (m = n->u.rdnSequence.len; m > 0; m--) { + size_t len; + i = m - 1; + + for (j = 0; j < n->u.rdnSequence.val[i].len; j++) { + DirectoryString *ds = &n->u.rdnSequence.val[i].val[j].value; + char *oidname; + char *ss; + + oidname = oidtostring(&n->u.rdnSequence.val[i].val[j].type, NULL); + + switch(ds->element) { + case choice_DirectoryString_ia5String: + ss = ds->u.ia5String.data; + len = ds->u.ia5String.length; + break; + case choice_DirectoryString_printableString: + ss = ds->u.printableString.data; + len = ds->u.printableString.length; + break; + case choice_DirectoryString_utf8String: + ss = ds->u.utf8String; + len = strlen(ss); + break; + case choice_DirectoryString_bmpString: { + const uint16_t *bmp = ds->u.bmpString.data; + size_t bmplen = ds->u.bmpString.length; + size_t k; + + ret = wind_ucs2utf8_length(bmp, bmplen, &k); + if (ret) { + free(oidname); + free(*str); + *str = NULL; + return ret; + } + + ss = malloc(k + 1); + if (ss == NULL) + _hx509_abort("allocation failure"); /* XXX */ + ret = wind_ucs2utf8(bmp, bmplen, ss, NULL); + if (ret) { + free(oidname); + free(ss); + free(*str); + *str = NULL; + return ret; + } + ss[k] = '\0'; + len = k; + break; + } + case choice_DirectoryString_teletexString: + ss = ds->u.teletexString; + len = strlen(ss); + break; + case choice_DirectoryString_universalString: { + const uint32_t *uni = ds->u.universalString.data; + size_t unilen = ds->u.universalString.length; + size_t k; + + ret = wind_ucs4utf8_length(uni, unilen, &k); + if (ret) { + free(oidname); + free(*str); + *str = NULL; + return ret; + } + + ss = malloc(k + 1); + if (ss == NULL) + _hx509_abort("allocation failure"); /* XXX */ + ret = wind_ucs4utf8(uni, unilen, ss, NULL); + if (ret) { + free(ss); + free(oidname); + free(*str); + *str = NULL; + return ret; + } + ss[k] = '\0'; + len = k; + break; + } + default: + _hx509_abort("unknown directory type: %d", ds->element); + exit(1); + } + append_string(str, &total_len, oidname, strlen(oidname), 0); + free(oidname); + append_string(str, &total_len, "=", 1, 0); + append_string(str, &total_len, ss, len, 1); + if (ds->element == choice_DirectoryString_bmpString || + ds->element == choice_DirectoryString_universalString) + { + free(ss); + } + if (j + 1 < n->u.rdnSequence.val[i].len) + append_string(str, &total_len, "+", 1, 0); + } + + if (i > 0) + append_string(str, &total_len, ",", 1, 0); + } + return 0; +} + +#define COPYCHARARRAY(_ds,_el,_l,_n) \ + (_l) = strlen(_ds->u._el); \ + (_n) = malloc((_l + 1) * sizeof((_n)[0])); \ + if ((_n) == NULL) \ + return ENOMEM; \ + for (i = 0; i < (_l); i++) \ + (_n)[i] = _ds->u._el[i] + + +#define COPYVALARRAY(_ds,_el,_l,_n) \ + (_l) = _ds->u._el.length; \ + (_n) = malloc((_l + 1) * sizeof((_n)[0])); \ + if ((_n) == NULL) \ + return ENOMEM; \ + for (i = 0; i < (_l); i++) \ + (_n)[i] = _ds->u._el.data[i] + +#define COPYVOIDARRAY(_ds,_el,_l,_n) \ + (_l) = _ds->u._el.length; \ + (_n) = malloc((_l + 1) * sizeof((_n)[0])); \ + if ((_n) == NULL) \ + return ENOMEM; \ + for (i = 0; i < (_l); i++) \ + (_n)[i] = ((unsigned char *)_ds->u._el.data)[i] + + + +static int +dsstringprep(const DirectoryString *ds, uint32_t **rname, size_t *rlen) +{ + wind_profile_flags flags; + size_t i, len; + int ret = 0; + uint32_t *name; + + *rname = NULL; + *rlen = 0; + + switch(ds->element) { + case choice_DirectoryString_ia5String: + flags = WIND_PROFILE_LDAP; + COPYVOIDARRAY(ds, ia5String, len, name); + break; + case choice_DirectoryString_printableString: + flags = WIND_PROFILE_LDAP; + flags |= WIND_PROFILE_LDAP_CASE_EXACT_ATTRIBUTE; + COPYVOIDARRAY(ds, printableString, len, name); + break; + case choice_DirectoryString_teletexString: + flags = WIND_PROFILE_LDAP_CASE; + COPYCHARARRAY(ds, teletexString, len, name); + break; + case choice_DirectoryString_bmpString: + flags = WIND_PROFILE_LDAP; + COPYVALARRAY(ds, bmpString, len, name); + break; + case choice_DirectoryString_universalString: + flags = WIND_PROFILE_LDAP; + COPYVALARRAY(ds, universalString, len, name); + break; + case choice_DirectoryString_utf8String: + flags = WIND_PROFILE_LDAP; + ret = wind_utf8ucs4_length(ds->u.utf8String, &len); + if (ret) + return ret; + name = malloc((len + 1) * sizeof(name[0])); + if (name == NULL) + return ENOMEM; + ret = wind_utf8ucs4(ds->u.utf8String, name, &len); + if (ret) { + free(name); + return ret; + } + break; + default: + _hx509_abort("unknown directory type: %d", ds->element); + } + + *rlen = len; + /* try a couple of times to get the length right, XXX gross */ + for (i = 0; i < 4; i++) { + *rlen = *rlen * 2; + if ((*rname = malloc((rlen[0] + 1) * sizeof((*rname)[0]))) == NULL) { + ret = ENOMEM; + break; + } + + ret = wind_stringprep(name, len, *rname, rlen, flags); + if (ret == WIND_ERR_OVERRUN) { + free(*rname); + *rname = NULL; + continue; + } else + break; + } + free(name); + if (ret) { + if (*rname) + free(*rname); + *rname = NULL; + *rlen = 0; + return ret; + } + + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_name_ds_cmp(const DirectoryString *ds1, + const DirectoryString *ds2, + int *diff) +{ + uint32_t *ds1lp, *ds2lp; + size_t ds1len, ds2len, i; + int ret; + + ret = dsstringprep(ds1, &ds1lp, &ds1len); + if (ret) + return ret; + ret = dsstringprep(ds2, &ds2lp, &ds2len); + if (ret) { + free(ds1lp); + return ret; + } + + if (ds1len != ds2len) + *diff = ds1len - ds2len; + else { + for (i = 0; i < ds1len; i++) { + *diff = ds1lp[i] - ds2lp[i]; + if (*diff) + break; + } + } + free(ds1lp); + free(ds2lp); + + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_name_cmp(const Name *n1, const Name *n2, int *c) +{ + int ret; + size_t i, j; + + *c = n1->u.rdnSequence.len - n2->u.rdnSequence.len; + if (*c) + return 0; + + for (i = 0 ; i < n1->u.rdnSequence.len; i++) { + *c = n1->u.rdnSequence.val[i].len - n2->u.rdnSequence.val[i].len; + if (*c) + return 0; + + for (j = 0; j < n1->u.rdnSequence.val[i].len; j++) { + *c = der_heim_oid_cmp(&n1->u.rdnSequence.val[i].val[j].type, + &n1->u.rdnSequence.val[i].val[j].type); + if (*c) + return 0; + + ret = _hx509_name_ds_cmp(&n1->u.rdnSequence.val[i].val[j].value, + &n2->u.rdnSequence.val[i].val[j].value, + c); + if (ret) + return ret; + if (*c) + return 0; + } + } + *c = 0; + return 0; +} + +/** + * Compare to hx509 name object, useful for sorting. + * + * @param n1 a hx509 name object. + * @param n2 a hx509 name object. + * + * @return 0 the objects are the same, returns > 0 is n2 is "larger" + * then n2, < 0 if n1 is "smaller" then n2. + * + * @ingroup hx509_name + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_name_cmp(hx509_name n1, hx509_name n2) +{ + int ret, diff; + ret = _hx509_name_cmp(&n1->der_name, &n2->der_name, &diff); + if (ret) + return ret; + return diff; +} + + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_name_from_Name(const Name *n, hx509_name *name) +{ + int ret; + *name = calloc(1, sizeof(**name)); + if (*name == NULL) + return ENOMEM; + ret = copy_Name(n, &(*name)->der_name); + if (ret) { + free(*name); + *name = NULL; + } + return ret; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_name_modify(hx509_context context, + Name *name, + int append, + const heim_oid *oid, + const char *str) +{ + RelativeDistinguishedName rdn; + size_t max_len = oidtomaxlen(oid); + char *s = NULL; + int type_choice = choice_DirectoryString_printableString; + int ret; + + /* + * Check string length upper bounds. + * + * Because we don't have these bounds in our copy of the PKIX ASN.1 module, + * and because we might like to catch these early anyways, we enforce them + * here. + */ + if (max_len && strlen(str) > max_len) { + char *a = oidtostring(oid, &type_choice); + + ret = HX509_PARSING_NAME_FAILED; + hx509_set_error_string(context, 0, ret, "RDN attribute %s value too " + "long (max %llu): %s", a ? a : "<unknown>", + max_len, str); + free(a); + return ret; + } + + memset(&rdn, 0, sizeof(rdn)); + if ((rdn.val = malloc(sizeof(rdn.val[0]))) == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "Out of memory"); + return ENOMEM; + } + rdn.len = 1; + + /* + * How best to pick a type for this attribute value? + * + * Options: + * + * 1) the API deals only in UTF-8, let the callers convert to/from UTF-8 + * and whatever the current locale wants + * + * 2) use the best type for the codeset of the current locale. + * + * We choose (1). + * + * However, for some cases we really should prefer other types when the + * input string is all printable ASCII. + */ + rdn.val[0].value.element = type_choice; + if ((s = strdup(str)) == NULL || + der_copy_oid(oid, &rdn.val[0].type)) { + free(rdn.val); + free(s); + return hx509_enomem(context); + } + switch (rdn.val[0].value.element) { + /* C strings: */ + case choice_DirectoryString_utf8String: + rdn.val[0].value.u.utf8String = s; + break; + case choice_DirectoryString_teletexString: + rdn.val[0].value.u.teletexString = s; + break; + + /* Length and pointer */ + case choice_DirectoryString_ia5String: + rdn.val[0].value.u.ia5String.data = s; + rdn.val[0].value.u.ia5String.length = strlen(s); + break; + case choice_DirectoryString_printableString: + rdn.val[0].value.u.printableString.data = s; + rdn.val[0].value.u.printableString.length = strlen(s); + break; + case choice_DirectoryString_universalString: + free(s); + free(rdn.val); + hx509_set_error_string(context, 0, ENOTSUP, "UniversalString not supported"); + return ENOTSUP; + case choice_DirectoryString_bmpString: + free(s); + free(rdn.val); + hx509_set_error_string(context, 0, ENOTSUP, "BMPString not supported"); + return ENOTSUP; + default: + free(s); + free(rdn.val); + hx509_set_error_string(context, 0, ENOTSUP, + "Internal error; unknown DirectoryString choice"); + return ENOTSUP; + } + + /* Append RDN. If the caller wanted to prepend instead, we'll rotate. */ + ret = add_RDNSequence(&name->u.rdnSequence, &rdn); + free_RelativeDistinguishedName(&rdn); + + if (ret || append || name->u.rdnSequence.len < 2) + return ret; + + /* Rotate */ + rdn = name->u.rdnSequence.val[name->u.rdnSequence.len - 1]; + memmove(&name->u.rdnSequence.val[1], + &name->u.rdnSequence.val[0], + (name->u.rdnSequence.len - 1) * + sizeof(name->u.rdnSequence.val[0])); + name->u.rdnSequence.val[0] = rdn; + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_empty_name(hx509_context context, hx509_name *name) +{ + if ((*name = calloc(1, sizeof(**name))) == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + (*name)->der_name.element = choice_Name_rdnSequence; + (*name)->der_name.u.rdnSequence.val = 0; + (*name)->der_name.u.rdnSequence.len = 0; + return 0; +} + +/** + * Parse a string into a hx509 name object. + * + * @param context A hx509 context. + * @param str a string to parse. + * @param name the resulting object, NULL in case of error. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_name + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_parse_name(hx509_context context, const char *str, hx509_name *name) +{ + const char *p, *q; + size_t len; + hx509_name n; + int ret; + + *name = NULL; + + n = calloc(1, sizeof(*n)); + if (n == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + + n->der_name.element = choice_Name_rdnSequence; + + p = str; + + while (p != NULL && *p != '\0') { + heim_oid oid; + int last; + + q = strchr(p, ','); + if (q) { + len = (q - p); + last = 1; + } else { + len = strlen(p); + last = 0; + } + + q = strchr(p, '='); + if (q == NULL) { + ret = HX509_PARSING_NAME_FAILED; + hx509_set_error_string(context, 0, ret, "missing = in %s", p); + goto out; + } + if (q == p) { + ret = HX509_PARSING_NAME_FAILED; + hx509_set_error_string(context, 0, ret, + "missing name before = in %s", p); + goto out; + } + + if ((size_t)(q - p) > len) { + ret = HX509_PARSING_NAME_FAILED; + hx509_set_error_string(context, 0, ret, " = after , in %s", p); + goto out; + } + + ret = stringtooid(p, q - p, &oid); + if (ret) { + ret = HX509_PARSING_NAME_FAILED; + hx509_set_error_string(context, 0, ret, + "unknown type: %.*s", (int)(q - p), p); + goto out; + } + + { + size_t pstr_len = len - (q - p) - 1; + const char *pstr = p + (q - p) + 1; + char *r; + + r = malloc(pstr_len + 1); + if (r == NULL) { + der_free_oid(&oid); + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "out of memory"); + goto out; + } + memcpy(r, pstr, pstr_len); + r[pstr_len] = '\0'; + + ret = _hx509_name_modify(context, &n->der_name, 0, &oid, r); + free(r); + der_free_oid(&oid); + if(ret) + goto out; + } + p += len + last; + } + + *name = n; + + return 0; +out: + hx509_name_free(&n); + return HX509_NAME_MALFORMED; +} + +/** + * Copy a hx509 name object. + * + * @param context A hx509 cotext. + * @param from the name to copy from + * @param to the name to copy to + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_name + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_name_copy(hx509_context context, const hx509_name from, hx509_name *to) +{ + int ret; + + *to = calloc(1, sizeof(**to)); + if (*to == NULL) + return ENOMEM; + ret = copy_Name(&from->der_name, &(*to)->der_name); + if (ret) { + free(*to); + *to = NULL; + return ENOMEM; + } + return 0; +} + +/** + * Convert a hx509_name into a Name. + * + * @param from the name to copy from + * @param to the name to copy to + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_name + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_name_to_Name(const hx509_name from, Name *to) +{ + return copy_Name(&from->der_name, to); +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_name_normalize(hx509_context context, hx509_name name) +{ + return 0; +} + +/** + * Expands variables in the name using env. Variables are on the form + * ${name}. Useful when dealing with certificate templates. + * + * @param context A hx509 cotext. + * @param name the name to expand. + * @param env environment variable to expand. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_name + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_name_expand(hx509_context context, + hx509_name name, + hx509_env env) +{ + Name *n = &name->der_name; + size_t i, j; + int bounds_check = 1; + + if (env == NULL) + return 0; + + if (n->element != choice_Name_rdnSequence) { + hx509_set_error_string(context, 0, EINVAL, "RDN not of supported type"); + return EINVAL; + } + + for (i = 0 ; i < n->u.rdnSequence.len; i++) { + for (j = 0; j < n->u.rdnSequence.val[i].len; j++) { + /** Only UTF8String rdnSequence names are allowed */ + /* + THIS SHOULD REALLY BE: + COMP = n->u.rdnSequence.val[i].val[j]; + normalize COMP to utf8 + check if there are variables + expand variables + convert back to orignal format, store in COMP + free normalized utf8 string + */ + DirectoryString *ds = &n->u.rdnSequence.val[i].val[j].value; + heim_oid *type = &n->u.rdnSequence.val[i].val[j].type; + const char *sval = NULL; + char *p, *p2; + char *s = NULL; + struct rk_strpool *strpool = NULL; + + switch (ds->element) { + case choice_DirectoryString_utf8String: + sval = ds->u.utf8String; + break; + case choice_DirectoryString_teletexString: + sval = ds->u.utf8String; + break; + case choice_DirectoryString_ia5String: + s = strndup(ds->u.ia5String.data, + ds->u.ia5String.length); + break; + case choice_DirectoryString_printableString: + s = strndup(ds->u.printableString.data, + ds->u.printableString.length); + break; + case choice_DirectoryString_universalString: + hx509_set_error_string(context, 0, ENOTSUP, "UniversalString not supported"); + return ENOTSUP; + case choice_DirectoryString_bmpString: + hx509_set_error_string(context, 0, ENOTSUP, "BMPString not supported"); + return ENOTSUP; + } + if (sval == NULL && s == NULL) + return hx509_enomem(context); + if (s) + sval = s; + + p = strstr(sval, "${"); + if (p) { + strpool = rk_strpoolprintf(strpool, "%.*s", (int)(p - sval), sval); + if (strpool == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + free(s); + return ENOMEM; + } + } + + while (p != NULL) { + /* expand variables */ + const char *value; + p2 = strchr(p, '}'); + if (p2 == NULL) { + hx509_set_error_string(context, 0, EINVAL, "missing }"); + rk_strpoolfree(strpool); + free(s); + return EINVAL; + } + p += 2; + value = hx509_env_lfind(context, env, p, p2 - p); + if (value == NULL) { + hx509_set_error_string(context, 0, EINVAL, + "variable %.*s missing", + (int)(p2 - p), p); + rk_strpoolfree(strpool); + free(s); + return EINVAL; + } + strpool = rk_strpoolprintf(strpool, "%s", value); + if (strpool == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + free(s); + return ENOMEM; + } + p2++; + + p = strstr(p2, "${"); + if (p) + strpool = rk_strpoolprintf(strpool, "%.*s", + (int)(p - p2), p2); + else + strpool = rk_strpoolprintf(strpool, "%s", p2); + if (strpool == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + free(s); + return ENOMEM; + } + } + + free(s); + s = NULL; + + if (strpool) { + size_t max_bytes; + + if ((s = rk_strpoolcollect(strpool)) == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + + /* Check upper bounds! */ + if ((max_bytes = oidtomaxlen(type)) && strlen(s) > max_bytes) + bounds_check = 0; + + switch (ds->element) { + /* C strings: */ + case choice_DirectoryString_utf8String: + free(ds->u.utf8String); + ds->u.utf8String = s; + break; + case choice_DirectoryString_teletexString: + free(ds->u.teletexString); + ds->u.teletexString = s; + break; + + /* Length and pointer */ + case choice_DirectoryString_ia5String: + free(ds->u.ia5String.data); + ds->u.ia5String.data = s; + ds->u.ia5String.length = strlen(s); + break; + case choice_DirectoryString_printableString: + free(ds->u.printableString.data); + ds->u.printableString.data = s; + ds->u.printableString.length = strlen(s); + break; + default: + break; /* Handled above */ + } + } + } + } + + if (!bounds_check) { + hx509_set_error_string(context, 0, HX509_PARSING_NAME_FAILED, + "some expanded RDNs are too long"); + return HX509_PARSING_NAME_FAILED; + } + return 0; +} + +/** + * Free a hx509 name object, upond return *name will be NULL. + * + * @param name a hx509 name object to be freed. + * + * @ingroup hx509_name + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_name_free(hx509_name *name) +{ + free_Name(&(*name)->der_name); + memset(*name, 0, sizeof(**name)); + free(*name); + *name = NULL; +} + +/** + * Convert a DER encoded name info a string. + * + * @param data data to a DER/BER encoded name + * @param length length of data + * @param str the resulting string, is NULL on failure. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_name + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_unparse_der_name(const void *data, size_t length, char **str) +{ + Name name; + int ret; + + *str = NULL; + + ret = decode_Name(data, length, &name, NULL); + if (ret) + return ret; + ret = _hx509_Name_to_string(&name, str); + free_Name(&name); + return ret; +} + +/** + * Convert a hx509_name object to DER encoded name. + * + * @param name name to concert + * @param os data to a DER encoded name, free the resulting octet + * string with hx509_xfree(os->data). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_name + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_name_binary(const hx509_name name, heim_octet_string *os) +{ + size_t size; + int ret; + + ASN1_MALLOC_ENCODE(Name, os->data, os->length, &name->der_name, &size, ret); + if (ret) + return ret; + if (os->length != size) + _hx509_abort("internal ASN.1 encoder error"); + + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_unparse_Name(const Name *aname, char **str) +{ + hx509_name name; + int ret; + + ret = _hx509_name_from_Name(aname, &name); + if (ret) + return ret; + + ret = hx509_name_to_string(name, str); + hx509_name_free(&name); + return ret; +} + +/** + * Check if a name is empty. + * + * @param name the name to check if its empty/null. + * + * @return non zero if the name is empty/null. + * + * @ingroup hx509_name + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_name_is_null_p(const hx509_name name) +{ + return name->der_name.element == choice_Name_rdnSequence && + name->der_name.u.rdnSequence.len == 0; +} + +int +_hx509_unparse_PermanentIdentifier(hx509_context context, + struct rk_strpool **strpool, + heim_any *value) +{ + PermanentIdentifier pi; + size_t len; + const char *pid = ""; + char *s = NULL; + int ret; + + ret = decode_PermanentIdentifier(value->data, value->length, &pi, &len); + if (ret == 0 && pi.assigner && + der_print_heim_oid(pi.assigner, '.', &s) != 0) + ret = hx509_enomem(context); + if (pi.identifierValue && *pi.identifierValue) + pid = *pi.identifierValue; + if (ret == 0 && + (*strpool = rk_strpoolprintf(*strpool, "%s:%s", s ? s : "", pid)) == NULL) + ret = hx509_enomem(context); + free_PermanentIdentifier(&pi); + free(s); + if (ret) { + rk_strpoolfree(*strpool); + *strpool = rk_strpoolprintf(NULL, + "<error-decoding-PermanentIdentifier"); + hx509_set_error_string(context, 0, ret, + "Failed to decode PermanentIdentifier"); + } + return ret; +} + +int +_hx509_unparse_HardwareModuleName(hx509_context context, + struct rk_strpool **strpool, + heim_any *value) +{ + HardwareModuleName hm; + size_t len; + char *s = NULL; + int ret; + + ret = decode_HardwareModuleName(value->data, value->length, &hm, &len); + if (ret == 0 && hm.hwSerialNum.length > 256) + hm.hwSerialNum.length = 256; + if (ret == 0) + ret = der_print_heim_oid(&hm.hwType, '.', &s); + if (ret == 0) { + *strpool = rk_strpoolprintf(*strpool, "%s:%.*s%s", s, + (int)hm.hwSerialNum.length, + (char *)hm.hwSerialNum.data, + value->length == len ? "" : ", <garbage>"); + if (*strpool == NULL) + ret = hx509_enomem(context); + } + free_HardwareModuleName(&hm); + free(s); + if (ret) { + rk_strpoolfree(*strpool); + *strpool = rk_strpoolprintf(NULL, + "<error-decoding-HardwareModuleName"); + hx509_set_error_string(context, 0, ret, + "Failed to decode HardwareModuleName"); + } + return ret; +} + +/* + * This necessarily duplicates code from libkrb5, and has to unless we move + * common code here or to lib/roken for it. We do have slightly different + * needs (e.g., we want space quoted, and we want to indicate whether we saw + * trailing garbage, we have no need for flags, no special realm treatment, + * etc) than the corresponding code in libkrb5, so for now we duplicate this + * code. + * + * The relevant RFCs here are RFC1964 for the string representation of Kerberos + * principal names, and RFC4556 for the KRB5PrincipalName ASN.1 type (Kerberos + * lacks such a type because on the wire the name and realm are sent + * separately as a form of cheap compression). + * + * Note that we cannot handle embedded NULs because of Heimdal's representation + * of ASN.1 strings as C strings. + */ +int +_hx509_unparse_KRB5PrincipalName(hx509_context context, + struct rk_strpool **strpool, + heim_any *value) +{ + KRB5PrincipalName kn; + size_t len; + int ret; + + ret = decode_KRB5PrincipalName(value->data, value->length, &kn, &len); + if (ret == 0 && + (*strpool = _hx509_unparse_kerberos_name(*strpool, &kn)) == NULL) + ret = hx509_enomem(context); + free_KRB5PrincipalName(&kn); + if (ret == 0 && (value->length != len) && + (*strpool = rk_strpoolprintf(*strpool, " <garbage>")) == NULL) + ret = hx509_enomem(context); + if (ret) { + rk_strpoolfree(*strpool); + *strpool = rk_strpoolprintf(NULL, + "<error-decoding-PrincipalName"); + hx509_set_error_string(context, 0, ret, + "Failed to decode PermanentIdentifier"); + } + return ret; +} + +struct rk_strpool * +_hx509_unparse_kerberos_name(struct rk_strpool *strpool, KRB5PrincipalName *kn) +{ + static const char comp_quotable_chars[] = " \n\t\b\\/@"; + static const char realm_quotable_chars[] = " \n\t\b\\@"; + const char *s; + size_t i, k, len, plen; + int need_slash = 0; + + for (i = 0; i < kn->principalName.name_string.len; i++) { + s = kn->principalName.name_string.val[i]; + len = strlen(s); + + if (need_slash) + strpool = rk_strpoolprintf(strpool, "/"); + need_slash = 1; + + for (k = 0; k < len; s += plen, k += plen) { + char c; + + plen = strcspn(s, comp_quotable_chars); + if (plen) + strpool = rk_strpoolprintf(strpool, "%.*s", (int)plen, s); + if (k + plen >= len) + continue; + switch ((c = s[plen++])) { + case '\n': strpool = rk_strpoolprintf(strpool, "\\n"); break; + case '\t': strpool = rk_strpoolprintf(strpool, "\\t"); break; + case '\b': strpool = rk_strpoolprintf(strpool, "\\b"); break; + /* default -> '@', ' ', '\\', or '/' */ + default: strpool = rk_strpoolprintf(strpool, "\\%c", c); break; + } + } + } + if (!kn->realm) + return strpool; + strpool = rk_strpoolprintf(strpool, "@"); + + s = kn->realm; + len = strlen(kn->realm); + for (k = 0; k < len; s += plen, k += plen) { + char c; + + plen = strcspn(s, realm_quotable_chars); + if (plen) + strpool = rk_strpoolprintf(strpool, "%.*s", (int)plen, s); + if (k + plen >= len) + continue; + switch ((c = s[plen++])) { + case '\n': strpool = rk_strpoolprintf(strpool, "\\n"); break; + case '\t': strpool = rk_strpoolprintf(strpool, "\\t"); break; + case '\b': strpool = rk_strpoolprintf(strpool, "\\b"); break; + /* default -> '@', ' ', or '\\' */ + default: strpool = rk_strpoolprintf(strpool, "\\%c", c); break; + } + } + return strpool; +} + +int +_hx509_unparse_utf8_string_name(hx509_context context, + struct rk_strpool **strpool, + heim_any *value) +{ + PKIXXmppAddr us; + size_t size; + int ret; + + ret = decode_PKIXXmppAddr(value->data, value->length, &us, &size); + if (ret == 0 && + (*strpool = rk_strpoolprintf(*strpool, "%s", us)) == NULL) + ret = hx509_enomem(context); + if (ret) { + rk_strpoolfree(*strpool); + *strpool = rk_strpoolprintf(NULL, + "<error-decoding-UTF8String-SAN>"); + hx509_set_error_string(context, 0, ret, + "Failed to decode UTF8String SAN"); + } + free_PKIXXmppAddr(&us); + return ret; +} + +int +_hx509_unparse_ia5_string_name(hx509_context context, + struct rk_strpool **strpool, + heim_any *value) +{ + SRVName us; + size_t size; + int ret; + + ret = decode_SRVName(value->data, value->length, &us, &size); + if (ret == 0) { + rk_strpoolfree(*strpool); + *strpool = rk_strpoolprintf(NULL, + "<error-decoding-IA5String-SAN>"); + hx509_set_error_string(context, 0, ret, + "Failed to decode UTF8String SAN"); + return ret; + } + *strpool = rk_strpoolprintf(*strpool, "%.*s", + (int)us.length, (char *)us.data); + free_SRVName(&us); + return ret; +} + +typedef int (*other_unparser_f)(hx509_context, + struct rk_strpool **, + heim_any *); + +struct { + const heim_oid *oid; + const char *friendly_name; + other_unparser_f f; +} o_unparsers[] = { + { &asn1_oid_id_pkinit_san, + "KerberosPrincipalName", + _hx509_unparse_KRB5PrincipalName }, + { &asn1_oid_id_pkix_on_permanentIdentifier, + "PermanentIdentifier", + _hx509_unparse_PermanentIdentifier }, + { &asn1_oid_id_on_hardwareModuleName, + "HardwareModuleName", + _hx509_unparse_HardwareModuleName }, + { &asn1_oid_id_pkix_on_xmppAddr, + "XMPPName", + _hx509_unparse_utf8_string_name }, + { &asn1_oid_id_pkinit_ms_san, + "MSFTKerberosPrincipalName", + _hx509_unparse_utf8_string_name }, + { &asn1_oid_id_pkix_on_dnsSRV, + "SRVName", + _hx509_unparse_ia5_string_name }, +}; + +/** + * Unparse the hx509 name in name into a string. + * + * @param name the name to print + * @param str an allocated string returns the name in string form + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_name + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_general_name_unparse(GeneralName *name, char **str) +{ + hx509_context context; + int ret; + + if ((ret = hx509_context_init(&context))) + return ret; + ret = hx509_general_name_unparse2(context, name, str); + hx509_context_free(&context); + return ret; +} + +/** + * Unparse the hx509 name in name into a string. + * + * @param context hx509 library context + * @param name the name to print + * @param str an allocated string returns the name in string form + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_name + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_general_name_unparse2(hx509_context context, + GeneralName *name, + char **str) +{ + struct rk_strpool *strpool = NULL; + int ret = 0; + + *str = NULL; + + switch (name->element) { + case choice_GeneralName_otherName: { + size_t i; + char *oid; + + ret = hx509_oid_sprint(&name->u.otherName.type_id, &oid); + if (ret == 0) + strpool = rk_strpoolprintf(strpool, "otherName: %s ", oid); + if (strpool == NULL) + ret = ENOMEM; + + for (i = 0; ret == 0 && i < sizeof(o_unparsers)/sizeof(o_unparsers[0]); i++) { + if (der_heim_oid_cmp(&name->u.otherName.type_id, + o_unparsers[i].oid)) + continue; + strpool = rk_strpoolprintf(strpool, "%s ",o_unparsers[i].friendly_name); + if (strpool == NULL) + ret = ENOMEM; + if (ret == 0) + ret = o_unparsers[i].f(context, &strpool, &name->u.otherName.value); + break; + } + if (ret == 0 && i == sizeof(o_unparsers)/sizeof(o_unparsers[0])) { + strpool = rk_strpoolprintf(strpool, "<unknown-other-name-type>"); + ret = ENOTSUP; + } + free(oid); + break; + } + case choice_GeneralName_rfc822Name: + strpool = rk_strpoolprintf(strpool, "rfc822Name: %.*s", + (int)name->u.rfc822Name.length, + (char *)name->u.rfc822Name.data); + break; + case choice_GeneralName_dNSName: + strpool = rk_strpoolprintf(strpool, "dNSName: %.*s", + (int)name->u.dNSName.length, + (char *)name->u.dNSName.data); + break; + case choice_GeneralName_directoryName: { + Name dir; + char *s; + memset(&dir, 0, sizeof(dir)); + dir.element = (enum Name_enum)name->u.directoryName.element; + dir.u.rdnSequence = name->u.directoryName.u.rdnSequence; + ret = _hx509_unparse_Name(&dir, &s); + if (ret) + return ret; + strpool = rk_strpoolprintf(strpool, "directoryName: %s", s); + free(s); + break; + } + case choice_GeneralName_uniformResourceIdentifier: + strpool = rk_strpoolprintf(strpool, "URI: %.*s", + (int)name->u.uniformResourceIdentifier.length, + (char *)name->u.uniformResourceIdentifier.data); + break; + case choice_GeneralName_iPAddress: { + unsigned char *a = name->u.iPAddress.data; + + strpool = rk_strpoolprintf(strpool, "IPAddress: "); + if (strpool == NULL) + break; + if (name->u.iPAddress.length == 4) + strpool = rk_strpoolprintf(strpool, "%d.%d.%d.%d", + a[0], a[1], a[2], a[3]); + else if (name->u.iPAddress.length == 16) + strpool = rk_strpoolprintf(strpool, + "%02X:%02X:%02X:%02X:" + "%02X:%02X:%02X:%02X:" + "%02X:%02X:%02X:%02X:" + "%02X:%02X:%02X:%02X", + a[0], a[1], a[2], a[3], + a[4], a[5], a[6], a[7], + a[8], a[9], a[10], a[11], + a[12], a[13], a[14], a[15]); + else + strpool = rk_strpoolprintf(strpool, + "unknown IP address of length %lu", + (unsigned long)name->u.iPAddress.length); + break; + } + case choice_GeneralName_registeredID: { + char *oid; + hx509_oid_sprint(&name->u.registeredID, &oid); + if (oid == NULL) + return ENOMEM; + strpool = rk_strpoolprintf(strpool, "registeredID: %s", oid); + free(oid); + break; + } + default: + return EINVAL; + } + if (ret) + rk_strpoolfree(strpool); + else if (strpool == NULL || (*str = rk_strpoolcollect(strpool)) == NULL) + return ENOMEM; + return ret; +} diff --git a/third_party/heimdal/lib/hx509/peer.c b/third_party/heimdal/lib/hx509/peer.c new file mode 100644 index 0000000..2501f01 --- /dev/null +++ b/third_party/heimdal/lib/hx509/peer.c @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" + +/** + * @page page_peer Hx509 crypto selecting functions + * + * Peer info structures are used togeter with hx509_crypto_select() to + * select the best avaible crypto algorithm to use. + * + * See the library functions here: @ref hx509_peer + */ + +/** + * Allocate a new peer info structure an init it to default values. + * + * @param context A hx509 context. + * @param peer return an allocated peer, free with hx509_peer_info_free(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_peer + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_peer_info_alloc(hx509_context context, hx509_peer_info *peer) +{ + *peer = calloc(1, sizeof(**peer)); + if (*peer == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + return 0; +} + + +static void +free_cms_alg(hx509_peer_info peer) +{ + if (peer->val) { + size_t i; + for (i = 0; i < peer->len; i++) + free_AlgorithmIdentifier(&peer->val[i]); + free(peer->val); + peer->val = NULL; + peer->len = 0; + } +} + +/** + * Free a peer info structure. + * + * @param peer peer info to be freed. + * + * @ingroup hx509_peer + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_peer_info_free(hx509_peer_info peer) +{ + if (peer == NULL) + return; + if (peer->cert) + hx509_cert_free(peer->cert); + free_cms_alg(peer); + memset(peer, 0, sizeof(*peer)); + free(peer); +} + +/** + * Set the certificate that remote peer is using. + * + * @param peer peer info to update + * @param cert cerificate of the remote peer. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_peer + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_peer_info_set_cert(hx509_peer_info peer, + hx509_cert cert) +{ + if (peer->cert) + hx509_cert_free(peer->cert); + peer->cert = hx509_cert_ref(cert); + return 0; +} + +/** + * Add an additional algorithm that the peer supports. + * + * @param context A hx509 context. + * @param peer the peer to set the new algorithms for + * @param val an AlgorithmsIdentier to add + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_peer + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_peer_info_add_cms_alg(hx509_context context, + hx509_peer_info peer, + const AlgorithmIdentifier *val) +{ + void *ptr; + int ret; + + ptr = realloc(peer->val, sizeof(peer->val[0]) * (peer->len + 1)); + if (ptr == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + peer->val = ptr; + ret = copy_AlgorithmIdentifier(val, &peer->val[peer->len]); + if (ret == 0) + peer->len += 1; + else + hx509_set_error_string(context, 0, ret, "out of memory"); + return ret; +} + +/** + * Set the algorithms that the peer supports. + * + * @param context A hx509 context. + * @param peer the peer to set the new algorithms for + * @param val array of supported AlgorithmsIdentiers + * @param len length of array val. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_peer + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_peer_info_set_cms_algs(hx509_context context, + hx509_peer_info peer, + const AlgorithmIdentifier *val, + size_t len) +{ + size_t i; + + free_cms_alg(peer); + + peer->val = calloc(len, sizeof(*peer->val)); + if (peer->val == NULL) { + peer->len = 0; + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + peer->len = len; + for (i = 0; i < len; i++) { + int ret; + ret = copy_AlgorithmIdentifier(&val[i], &peer->val[i]); + if (ret) { + hx509_clear_error_string(context); + free_cms_alg(peer); + return ret; + } + } + return 0; +} + +#if 0 + +/* + * S/MIME + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_peer_info_parse_smime(hx509_peer_info peer, + const heim_octet_string *data) +{ + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_peer_info_unparse_smime(hx509_peer_info peer, + heim_octet_string *data) +{ + return 0; +} + +/* + * For storing hx509_peer_info to be able to cache them. + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_peer_info_parse(hx509_peer_info peer, + const heim_octet_string *data) +{ + return 0; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_peer_info_unparse(hx509_peer_info peer, + heim_octet_string *data) +{ + return 0; +} +#endif diff --git a/third_party/heimdal/lib/hx509/print.c b/third_party/heimdal/lib/hx509/print.c new file mode 100644 index 0000000..3309913 --- /dev/null +++ b/third_party/heimdal/lib/hx509/print.c @@ -0,0 +1,1144 @@ +/* + * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" +#include <vis.h> +#include <vis-extras.h> + +/** + * @page page_print Hx509 printing functions + * + * See the library functions here: @ref hx509_print + */ + +struct hx509_validate_ctx_data { + hx509_context context; + int flags; + hx509_vprint_func vprint_func; + void *ctx; +}; + +struct cert_status { + unsigned int selfsigned:1; + unsigned int isca:1; + unsigned int isproxy:1; + unsigned int haveSAN:1; + unsigned int haveIAN:1; + unsigned int haveSKI:1; + unsigned int haveAKI:1; + unsigned int haveCRLDP:1; +}; + + +/* + * + */ + +static int +Time2string(const Time *T, char **str) +{ + time_t t; + char *s; + struct tm *tm; + + *str = NULL; + t = _hx509_Time2time_t(T); + tm = gmtime (&t); + s = malloc(30); + if (s == NULL) + return ENOMEM; + strftime(s, 30, "%Y-%m-%d %H:%M:%S", tm); + *str = s; + return 0; +} + +/** + * Helper function to print on stdout for: + * - hx509_oid_print(), + * - hx509_bitstring_print(), + * - hx509_validate_ctx_set_print(). + * + * @param ctx the context to the print function. If the ctx is NULL, + * stdout is used. + * @param fmt the printing format. + * @param va the argumet list. + * + * @ingroup hx509_print + */ + +HX509_LIB_FUNCTION void +hx509_print_stdout(void *ctx, const char *fmt, va_list va) +{ + FILE *f = ctx; + if (f == NULL) + f = stdout; + vfprintf(f, fmt, va); +} + +static void +print_func(hx509_vprint_func func, void *ctx, const char *fmt, ...) +{ + va_list va; + va_start(va, fmt); + (*func)(ctx, fmt, va); + va_end(va); +} + +/** + * Print a oid to a string. + * + * @param oid oid to print + * @param str allocated string, free with hx509_xfree(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_print + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_oid_sprint(const heim_oid *oid, char **str) +{ + return der_print_heim_oid(oid, '.', str); +} + +/** + * Print a oid using a hx509_vprint_func function. To print to stdout + * use hx509_print_stdout(). + * + * @param oid oid to print + * @param func hx509_vprint_func to print with. + * @param ctx context variable to hx509_vprint_func function. + * + * @ingroup hx509_print + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_oid_print(const heim_oid *oid, hx509_vprint_func func, void *ctx) +{ + char *str; + hx509_oid_sprint(oid, &str); + print_func(func, ctx, "%s", str); + free(str); +} + +/** + * Print a bitstring using a hx509_vprint_func function. To print to + * stdout use hx509_print_stdout(). + * + * @param b bit string to print. + * @param func hx509_vprint_func to print with. + * @param ctx context variable to hx509_vprint_func function. + * + * @ingroup hx509_print + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_bitstring_print(const heim_bit_string *b, + hx509_vprint_func func, void *ctx) +{ + size_t i; + print_func(func, ctx, "\tlength: %d\n\t", b->length); + for (i = 0; i < (b->length + 7) / 8; i++) + print_func(func, ctx, "%02x%s%s", + ((unsigned char *)b->data)[i], + i < (b->length - 7) / 8 + && (i == 0 || (i % 16) != 15) ? ":" : "", + i != 0 && (i % 16) == 15 ? + (i <= ((b->length + 7) / 8 - 2) ? "\n\t" : "\n"):""); +} + +/** + * Print certificate usage for a certificate to a string. + * + * @param context A hx509 context. + * @param c a certificate print the keyusage for. + * @param s the return string with the keysage printed in to, free + * with hx509_xfree(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_print + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_cert_keyusage_print(hx509_context context, hx509_cert c, char **s) +{ + KeyUsage ku; + char buf[256]; + int ret; + + *s = NULL; + + ret = _hx509_cert_get_keyusage(context, c, &ku); + if (ret) + return ret; + unparse_flags(KeyUsage2int(ku), asn1_KeyUsage_units(), buf, sizeof(buf)); + *s = strdup(buf); + if (*s == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + + return 0; +} + +/* + * + */ + +static void +validate_vprint(void *c, const char *fmt, va_list va) +{ + hx509_validate_ctx ctx = c; + if (ctx->vprint_func == NULL) + return; + (ctx->vprint_func)(ctx->ctx, fmt, va); +} + +static void +validate_print(hx509_validate_ctx ctx, int flags, const char *fmt, ...) +{ + va_list va; + if ((ctx->flags & flags) == 0) + return; + va_start(va, fmt); + validate_vprint(ctx, fmt, va); + va_end(va); +} + +/* + * Don't Care, SHOULD critical, SHOULD NOT critical, MUST critical, + * MUST NOT critical + */ +enum critical_flag { D_C = 0, S_C, S_N_C, M_C, M_N_C }; + +static int +check_Null(hx509_validate_ctx ctx, + struct cert_status *status, + enum critical_flag cf, const Extension *e) +{ + switch(cf) { + case D_C: + break; + case S_C: + if (!e->critical) + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "\tCritical not set on SHOULD\n"); + break; + case S_N_C: + if (e->critical) + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "\tCritical set on SHOULD NOT\n"); + break; + case M_C: + if (!e->critical) + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "\tCritical not set on MUST\n"); + break; + case M_N_C: + if (e->critical) + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "\tCritical set on MUST NOT\n"); + break; + default: + _hx509_abort("internal check_Null state error"); + } + return 0; +} + +static int +check_subjectKeyIdentifier(hx509_validate_ctx ctx, + struct cert_status *status, + enum critical_flag cf, + const Extension *e) +{ + SubjectKeyIdentifier si; + size_t size; + int ret; + + status->haveSKI = 1; + check_Null(ctx, status, cf, e); + + ret = decode_SubjectKeyIdentifier(e->extnValue.data, + e->extnValue.length, + &si, &size); + if (ret) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Decoding SubjectKeyIdentifier failed: %d", ret); + return 1; + } + if (size != e->extnValue.length) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Decoding SKI ahve extra bits on the end"); + return 1; + } + if (si.length == 0) + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "SKI is too short (0 bytes)"); + if (si.length > 20) + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "SKI is too long"); + + { + char *id; + hex_encode(si.data, si.length, &id); + if (id) { + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + "\tsubject key id: %s\n", id); + free(id); + } + } + + free_SubjectKeyIdentifier(&si); + + return 0; +} + +static int +check_authorityKeyIdentifier(hx509_validate_ctx ctx, + struct cert_status *status, + enum critical_flag cf, + const Extension *e) +{ + AuthorityKeyIdentifier ai; + size_t size; + int ret; + + status->haveAKI = 1; + check_Null(ctx, status, cf, e); + + ret = decode_AuthorityKeyIdentifier(e->extnValue.data, + e->extnValue.length, + &ai, &size); + if (ret) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Decoding AuthorityKeyIdentifier failed: %d", ret); + return 1; + } + if (size != e->extnValue.length) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Decoding SKI ahve extra bits on the end"); + return 1; + } + + if (ai.keyIdentifier) { + char *id; + hex_encode(ai.keyIdentifier->data, ai.keyIdentifier->length, &id); + if (id) { + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + "\tauthority key id: %s\n", id); + free(id); + } + } + + free_AuthorityKeyIdentifier(&ai); + return 0; +} + +static int +check_extKeyUsage(hx509_validate_ctx ctx, + struct cert_status *status, + enum critical_flag cf, + const Extension *e) +{ + ExtKeyUsage eku; + size_t size, i; + int ret; + + check_Null(ctx, status, cf, e); + + ret = decode_ExtKeyUsage(e->extnValue.data, + e->extnValue.length, + &eku, &size); + if (ret) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Decoding ExtKeyUsage failed: %d", ret); + return 1; + } + if (size != e->extnValue.length) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Padding data in EKU"); + free_ExtKeyUsage(&eku); + return 1; + } + if (eku.len == 0) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "ExtKeyUsage length is 0"); + return 1; + } + + for (i = 0; i < eku.len; i++) { + char *str; + ret = der_print_heim_oid (&eku.val[i], '.', &str); + if (ret) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "\tEKU: failed to print oid %d", i); + free_ExtKeyUsage(&eku); + return 1; + } + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + "\teku-%d: %s\n", i, str);; + free(str); + } + + free_ExtKeyUsage(&eku); + + return 0; +} + +static int +check_CRLDistributionPoints(hx509_validate_ctx ctx, + struct cert_status *status, + enum critical_flag cf, + const Extension *e) +{ + CRLDistributionPoints dp; + size_t size; + int ret; + size_t i; + + check_Null(ctx, status, cf, e); + + ret = decode_CRLDistributionPoints(e->extnValue.data, + e->extnValue.length, + &dp, &size); + if (ret) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Decoding CRL Distribution Points failed: %d\n", ret); + return 1; + } + + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "CRL Distribution Points:\n"); + for (i = 0 ; i < dp.len; i++) { + if (dp.val[i].distributionPoint) { + DistributionPointName dpname = dp.val[i].distributionPoint[0]; + size_t j; + + switch (dpname.element) { + case choice_DistributionPointName_fullName: + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "Fullname:\n"); + + for (j = 0 ; j < dpname.u.fullName.len; j++) { + char *s; + GeneralName *name = &dpname.u.fullName.val[j]; + + ret = hx509_general_name_unparse2(ctx->context, name, &s); + if (ret) { + s = hx509_get_error_string(ctx->context, ret); + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Unknown DistributionPointName: %s", s); + hx509_free_error_string(s); + } else { + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, " %s\n", s); + free(s); + } + } + break; + case choice_DistributionPointName_nameRelativeToCRLIssuer: + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + "Unknown nameRelativeToCRLIssuer"); + break; + default: + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Unknown DistributionPointName"); + break; + } + } + } + free_CRLDistributionPoints(&dp); + + status->haveCRLDP = 1; + + return 0; +} + +static int +check_altName(hx509_validate_ctx ctx, + struct cert_status *status, + const char *name, + enum critical_flag cf, + const Extension *e) +{ + GeneralNames gn; + size_t size; + int ret; + size_t i; + + check_Null(ctx, status, cf, e); + + if (e->extnValue.length == 0) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "%sAltName empty, not allowed", name); + return 1; + } + ret = decode_GeneralNames(e->extnValue.data, e->extnValue.length, + &gn, &size); + if (ret) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "\tret = %d while decoding %s GeneralNames\n", + ret, name); + return 1; + } + if (gn.len == 0) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "%sAltName generalName empty, not allowed\n", name); + return 1; + } + + for (i = 0; i < gn.len; i++) { + char *s; + + ret = hx509_general_name_unparse2(ctx->context, &gn.val[i], &s); + if (ret) { + s = hx509_get_error_string(ctx->context, ret); + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Error unparsing GeneralName: %s\n", s); + hx509_free_error_string(s); + return 1; + } + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "\t%s\n", s); + free(s); + } + + free_GeneralNames(&gn); + return 0; +} + +static int +check_subjectAltName(hx509_validate_ctx ctx, + struct cert_status *status, + enum critical_flag cf, + const Extension *e) +{ + status->haveSAN = 1; + return check_altName(ctx, status, "subject", cf, e); +} + +static int +check_issuerAltName(hx509_validate_ctx ctx, + struct cert_status *status, + enum critical_flag cf, + const Extension *e) +{ + status->haveIAN = 1; + return check_altName(ctx, status, "issuer", cf, e); +} + + +static int +check_basicConstraints(hx509_validate_ctx ctx, + struct cert_status *status, + enum critical_flag cf, + const Extension *e) +{ + BasicConstraints b; + size_t size; + int ret; + + check_Null(ctx, status, cf, e); + + ret = decode_BasicConstraints(e->extnValue.data, e->extnValue.length, + &b, &size); + if (ret) { + printf("\tret = %d while decoding BasicConstraints\n", ret); + return 0; + } + if (size != e->extnValue.length) + printf("\tlength of der data isn't same as extension\n"); + + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + "\tis %sa CA\n", b.cA ? "" : "NOT "); + if (b.pathLenConstraint) + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + "\tpathLenConstraint: %d\n", *b.pathLenConstraint); + + if (b.cA) { + if (!e->critical) + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Is a CA and not BasicConstraints CRITICAL\n"); + status->isca = 1; + } + free_BasicConstraints(&b); + + return 0; +} + +static int +check_proxyCertInfo(hx509_validate_ctx ctx, + struct cert_status *status, + enum critical_flag cf, + const Extension *e) +{ + check_Null(ctx, status, cf, e); + status->isproxy = 1; + return 0; +} + +static int +check_authorityInfoAccess(hx509_validate_ctx ctx, + struct cert_status *status, + enum critical_flag cf, + const Extension *e) +{ + AuthorityInfoAccessSyntax aia; + size_t size; + int ret; + size_t i; + + check_Null(ctx, status, cf, e); + + ret = decode_AuthorityInfoAccessSyntax(e->extnValue.data, + e->extnValue.length, + &aia, &size); + if (ret) { + printf("\tret = %d while decoding AuthorityInfoAccessSyntax\n", ret); + return 0; + } + + for (i = 0; i < aia.len; i++) { + char *str; + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + "\ttype: "); + hx509_oid_print(&aia.val[i].accessMethod, validate_vprint, ctx); + ret = hx509_general_name_unparse2(ctx->context, + &aia.val[i].accessLocation, &str); + if (ret) { + str = hx509_get_error_string(ctx->context, ret); + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Error unparsing AuthorityInfoAccessSyntax " + "accessLocation: %s", str); + hx509_free_error_string(str); + } else { + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + "\n\tdirname: %s\n", str); + free(str); + } + } + free_AuthorityInfoAccessSyntax(&aia); + + return ret; +} + +static int +get_display_text(DisplayText *dt, char **out) +{ + int r = -1; + + *out = NULL; + + /* + * XXX We're cheating with various string types here. + * + * Proper support for IA5String is a real pain, and we don't have it. + * + * We also don't have support for BMPString. + */ + switch (dt->element) { + case choice_DisplayText_ia5String: + r = rk_strasvisx(out, dt->u.ia5String.data, dt->u.ia5String.length, + VIS_CSTYLE | VIS_TAB | VIS_NL, ""); + break; + case choice_DisplayText_visibleString: + r = rk_strasvis(out, dt->u.visibleString, + VIS_CSTYLE | VIS_TAB | VIS_NL, ""); + break; + case choice_DisplayText_bmpString: + errno = ENOTSUP; /* XXX Need a UTF-16 -> UTF-8 conversion */ + break; + case choice_DisplayText_utf8String: + r = rk_strasvis(out, dt->u.visibleString, + VIS_CSTYLE | VIS_TAB | VIS_NL, ""); + break; + default: + errno = EINVAL; + } + return r < 0 ? errno : 0; +} + +static int +check_certificatePolicies(hx509_validate_ctx ctx, + struct cert_status *status, + enum critical_flag cf, + const Extension *e) +{ + CertificatePolicies cp; + size_t i, size; + int ret = 0; + + check_Null(ctx, status, cf, e); + + if (e->extnValue.length == 0) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "CertificatePolicies empty, not allowed"); + return 1; + } + ret = decode_CertificatePolicies(e->extnValue.data, e->extnValue.length, + &cp, &size); + if (ret) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "\tret = %d while decoding CertificatePolicies\n", ret); + return 1; + } + if (cp.len == 0) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "CertificatePolicies empty, not allowed\n"); + return 1; + } + + for (i = 0; ret == 0 && i < cp.len; i++) { + size_t k; + char *poid = NULL; + char *qoid = NULL; + char *dt = NULL; + + ret = der_print_heim_oid(&cp.val[i].policyIdentifier, '.', &poid); + if (ret == 0) + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "\tPolicy: %s", poid); + + for (k = 0; + ret == 0 && cp.val[i].policyQualifiers && + k < cp.val[i].policyQualifiers->len; + k++) { + PolicyQualifierInfo *pi = &cp.val[i].policyQualifiers->val[k]; + + if (der_heim_oid_cmp(&pi->policyQualifierId, + &asn1_oid_id_pkix_qt_cps) == 0) { + CPSuri cps; + + ret = decode_CPSuri(pi->qualifier.data, pi->qualifier.length, + &cps, &size); + if (ret == 0) { + if (cps.length > 4096) + cps.length = 4096; + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + ":CPSuri:%.*s", + (int)cps.length, (char *)cps.data); + free_CPSuri(&cps); + } + } else if (der_heim_oid_cmp(&pi->policyQualifierId, + &asn1_oid_id_pkix_qt_unotice) == 0) { + UserNotice un; + + ret = decode_UserNotice(pi->qualifier.data, + pi->qualifier.length, &un, &size); + if (ret == 0) { + if (un.explicitText) { + /* + * get_display_text() will strvis to make it safer to + * print. + */ + ret = get_display_text(un.explicitText, &dt); + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + " UserNotice:DistplayText:%s", dt); + } else if (un.noticeRef) { + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + " UserNotice:NoticeRef:<noticeRef-not-supported>", + qoid); + } else { + ret = der_print_heim_oid(&pi->policyQualifierId, '.', + &qoid); + if (ret) + break; + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + " Unknown:%s", qoid); + } + free_UserNotice(&un); + } + } else { + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + ", qualifier %s:<unknown>", qoid); + } + free(qoid); + free(dt); + qoid = dt = 0; + } + if (ret == 0) { + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "\n"); + } else { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "\nOut of memory formatting certificate policy"); + ret = ENOMEM; + } + free(poid); + free(qoid); + free(dt); + poid = qoid = dt = 0; + } + + free_CertificatePolicies(&cp); + + return ret ? 1 : 0; +} + +static int +check_policyMappings(hx509_validate_ctx ctx, + struct cert_status *status, + enum critical_flag cf, + const Extension *e) +{ + PolicyMappings pm; + size_t i, size; + int ret = 0; + + check_Null(ctx, status, cf, e); + + if (e->extnValue.length == 0) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "PolicyMappings empty, not allowed"); + return 1; + } + ret = decode_PolicyMappings(e->extnValue.data, e->extnValue.length, + &pm, &size); + if (ret) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "\tret = %d while decoding PolicyMappings\n", ret); + return 1; + } + if (pm.len == 0) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "PolicyMappings empty, not allowed\n"); + return 1; + } + + for (i = 0; ret == 0 && i < pm.len; i++) { + char *idpoid = NULL; + char *sdpoid = NULL; + + ret = der_print_heim_oid(&pm.val[i].issuerDomainPolicy, '.', &idpoid); + if (ret == 0) + ret = der_print_heim_oid(&pm.val[i].subjectDomainPolicy, '.', + &sdpoid); + if (ret == 0) + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + "\tPolicy mapping %s -> %s\n", idpoid, sdpoid); + else + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "ret=%d while decoding PolicyMappings\n", ret); + free(sdpoid); + free(idpoid); + } + + free_PolicyMappings(&pm); + return 0; +} + +/* + * + */ + +struct { + const char *name; + const heim_oid *oid; + int (*func)(hx509_validate_ctx ctx, + struct cert_status *status, + enum critical_flag cf, + const Extension *); + enum critical_flag cf; +} check_extension[] = { +#define ext(name, checkname) #name, &asn1_oid_id_x509_ce_##name, check_##checkname + { ext(subjectDirectoryAttributes, Null), M_N_C }, + { ext(subjectKeyIdentifier, subjectKeyIdentifier), M_N_C }, + { ext(keyUsage, Null), S_C }, + { ext(subjectAltName, subjectAltName), M_N_C }, + { ext(issuerAltName, issuerAltName), S_N_C }, + { ext(basicConstraints, basicConstraints), D_C }, + { ext(cRLNumber, Null), M_N_C }, + { ext(cRLReason, Null), M_N_C }, + { ext(holdInstructionCode, Null), M_N_C }, + { ext(invalidityDate, Null), M_N_C }, + { ext(deltaCRLIndicator, Null), M_C }, + { ext(issuingDistributionPoint, Null), M_C }, + { ext(certificateIssuer, Null), M_C }, + { ext(nameConstraints, Null), M_C }, + { ext(cRLDistributionPoints, CRLDistributionPoints), S_N_C }, + { ext(certificatePolicies, certificatePolicies), 0 }, + { ext(policyMappings, policyMappings), M_N_C }, + { ext(authorityKeyIdentifier, authorityKeyIdentifier), M_N_C }, + { ext(policyConstraints, Null), D_C }, + { ext(extKeyUsage, extKeyUsage), D_C }, + { ext(freshestCRL, Null), M_N_C }, + { ext(inhibitAnyPolicy, Null), M_C }, +#undef ext +#define ext(name, checkname) #name, &asn1_oid_id_pkix_pe_##name, check_##checkname + { ext(proxyCertInfo, proxyCertInfo), M_C }, + { ext(authorityInfoAccess, authorityInfoAccess), M_C }, +#undef ext + { "US Fed PKI - PIV Interim", &asn1_oid_id_uspkicommon_piv_interim, + check_Null, D_C }, + { "Netscape cert comment", &asn1_oid_id_netscape_cert_comment, + check_Null, D_C }, + { NULL, NULL, NULL, 0 } +}; + +/** + * Allocate a hx509 validation/printing context. + * + * @param context A hx509 context. + * @param ctx a new allocated hx509 validation context, free with + * hx509_validate_ctx_free(). + + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_print + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_validate_ctx_init(hx509_context context, hx509_validate_ctx *ctx) +{ + *ctx = calloc(1, sizeof(**ctx)); + if (*ctx == NULL) + return hx509_enomem(context); + (*ctx)->context = context; + return 0; +} + +/** + * Set the printing functions for the validation context. + * + * @param ctx a hx509 valication context. + * @param func the printing function to usea. + * @param c the context variable to the printing function. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_print + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_validate_ctx_set_print(hx509_validate_ctx ctx, + hx509_vprint_func func, + void *c) +{ + ctx->vprint_func = func; + ctx->ctx = c; +} + +/** + * Add flags to control the behaivor of the hx509_validate_cert() + * function. + * + * @param ctx A hx509 validation context. + * @param flags flags to add to the validation context. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_print + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_validate_ctx_add_flags(hx509_validate_ctx ctx, int flags) +{ + ctx->flags |= flags; +} + +/** + * Free an hx509 validate context. + * + * @param ctx the hx509 validate context to free. + * + * @ingroup hx509_print + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_validate_ctx_free(hx509_validate_ctx ctx) +{ + free(ctx); +} + +/** + * Validate/Print the status of the certificate. + * + * @param context A hx509 context. + * @param ctx A hx509 validation context. + * @param cert the cerificate to validate/print. + + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_print + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_validate_cert(hx509_context context, + hx509_validate_ctx ctx, + hx509_cert cert) +{ + Certificate *c = _hx509_get_cert(cert); + TBSCertificate *t = &c->tbsCertificate; + hx509_name issuer, subject; + char *str; + struct cert_status status; + int ret; + + memset(&status, 0, sizeof(status)); + + if (_hx509_cert_get_version(c) != 3) + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + "Not version 3 certificate\n"); + + if ((t->version == NULL || *t->version < 2) && t->extensions) + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Not version 3 certificate with extensions\n"); + + if (_hx509_cert_get_version(c) >= 3 && t->extensions == NULL) + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Version 3 certificate without extensions\n"); + + ret = hx509_cert_get_subject(cert, &subject); + if (ret) abort(); + hx509_name_to_string(subject, &str); + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + "subject name: %s\n", str); + free(str); + + ret = hx509_cert_get_issuer(cert, &issuer); + if (ret) abort(); + hx509_name_to_string(issuer, &str); + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + "issuer name: %s\n", str); + free(str); + + if (hx509_name_cmp(subject, issuer) == 0) { + status.selfsigned = 1; + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + "\tis a self-signed certificate\n"); + } + + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + "Validity:\n"); + + Time2string(&t->validity.notBefore, &str); + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "\tnotBefore %s\n", str); + free(str); + Time2string(&t->validity.notAfter, &str); + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "\tnotAfter %s\n", str); + free(str); + + if (t->extensions) { + size_t i, j; + + if (t->extensions->len == 0) { + validate_print(ctx, + HX509_VALIDATE_F_VALIDATE|HX509_VALIDATE_F_VERBOSE, + "The empty extensions list is not " + "allowed by PKIX\n"); + } + + for (i = 0; i < t->extensions->len; i++) { + + for (j = 0; check_extension[j].name; j++) + if (der_heim_oid_cmp(check_extension[j].oid, + &t->extensions->val[i].extnID) == 0) + break; + if (check_extension[j].name == NULL) { + int flags = HX509_VALIDATE_F_VERBOSE; + if (t->extensions->val[i].critical) + flags |= HX509_VALIDATE_F_VALIDATE; + validate_print(ctx, flags, "don't know what "); + if (t->extensions->val[i].critical) + validate_print(ctx, flags, "and is CRITICAL "); + if (ctx->flags & flags) + hx509_oid_print(&t->extensions->val[i].extnID, + validate_vprint, ctx); + validate_print(ctx, flags, " is\n"); + continue; + } + validate_print(ctx, + HX509_VALIDATE_F_VALIDATE|HX509_VALIDATE_F_VERBOSE, + "checking extension: %s\n", + check_extension[j].name); + (*check_extension[j].func)(ctx, + &status, + check_extension[j].cf, + &t->extensions->val[i]); + } + } else + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "no extensions\n"); + + if (status.isca) { + if (!status.haveSKI) + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "CA certificate have no SubjectKeyIdentifier\n"); + + } else { + if (!status.haveAKI) + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Is not CA and doesn't have " + "AuthorityKeyIdentifier\n"); + } + + + if (!status.haveSKI) + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Doesn't have SubjectKeyIdentifier\n"); + + if (status.isproxy && status.isca) + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Proxy and CA at the same time!\n"); + + if (status.isproxy) { + if (status.haveSAN) + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Proxy and have SAN\n"); + if (status.haveIAN) + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Proxy and have IAN\n"); + } + + if (hx509_name_is_null_p(subject) && !status.haveSAN) + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "NULL subject DN and doesn't have a SAN\n"); + + if (!status.selfsigned && !status.haveCRLDP) + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Not a CA nor PROXY and doesn't have" + "CRL Dist Point\n"); + + if (status.selfsigned) { + ret = _hx509_verify_signature_bitstring(context, + cert, + &c->signatureAlgorithm, + &c->tbsCertificate._save, + &c->signatureValue); + if (ret == 0) + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + "Self-signed certificate was self-signed\n"); + else + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Self-signed certificate NOT really self-signed!\n"); + } + + hx509_name_free(&subject); + hx509_name_free(&issuer); + + return 0; +} diff --git a/third_party/heimdal/lib/hx509/quote.py b/third_party/heimdal/lib/hx509/quote.py new file mode 100644 index 0000000..41887e5 --- /dev/null +++ b/third_party/heimdal/lib/hx509/quote.py @@ -0,0 +1,101 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Copyright (c) 2010 Kungliga Tekniska Högskolan +# (Royal Institute of Technology, Stockholm, Sweden). +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Institute nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +CONTROL_CHAR = 1 +PRINTABLE = 2 +RFC2253_QUOTE_FIRST = 4 +RFC2253_QUOTE_LAST = 8 +RFC2253_QUOTE = 16 +RFC2253_HEX = 32 + +chars = [] + +for i in range(0, 256): + chars.append(0); + +for i in range(0, 256): + if (i < 32 or i > 126): + chars[i] |= CONTROL_CHAR | RFC2253_HEX; + +for i in range(ord("A"), ord("Z") + 1): + chars[i] |= PRINTABLE +for i in range(ord("a"), ord("z") + 1): + chars[i] |= PRINTABLE +for i in range(ord("0"), ord("9") + 1): + chars[i] |= PRINTABLE + +chars[ord(' ')] |= PRINTABLE +chars[ord('+')] |= PRINTABLE +chars[ord(',')] |= PRINTABLE +chars[ord('-')] |= PRINTABLE +chars[ord('.')] |= PRINTABLE +chars[ord('/')] |= PRINTABLE +chars[ord(':')] |= PRINTABLE +chars[ord('=')] |= PRINTABLE +chars[ord('?')] |= PRINTABLE + +chars[ord(' ')] |= RFC2253_QUOTE_FIRST | RFC2253_QUOTE_FIRST + +chars[ord(',')] |= RFC2253_QUOTE +chars[ord('=')] |= RFC2253_QUOTE +chars[ord('+')] |= RFC2253_QUOTE +chars[ord('<')] |= RFC2253_QUOTE +chars[ord('>')] |= RFC2253_QUOTE +chars[ord('#')] |= RFC2253_QUOTE +chars[ord(';')] |= RFC2253_QUOTE + +print "#define Q_CONTROL_CHAR 1" +print "#define Q_PRINTABLE 2" +print "#define Q_RFC2253_QUOTE_FIRST 4" +print "#define Q_RFC2253_QUOTE_LAST 8" +print "#define Q_RFC2253_QUOTE 16" +print "#define Q_RFC2253_HEX 32" +print "" +print "#define Q_RFC2253 (Q_RFC2253_QUOTE_FIRST|Q_RFC2253_QUOTE_LAST|Q_RFC2253_QUOTE|Q_RFC2253_HEX)" +print "\n" * 2 + + + + +print "unsigned char char_map[] = {\n\t", +for x in range(0, 256): + if (x % 8) == 0 and x != 0: + print "\n\t", + print "0x%(char)02x" % { 'char' : chars[x] }, + if x < 255: + print ", ", + else: + print "" +print "};" diff --git a/third_party/heimdal/lib/hx509/ref/pkcs11.h b/third_party/heimdal/lib/hx509/ref/pkcs11.h new file mode 100644 index 0000000..a294c5e --- /dev/null +++ b/third_party/heimdal/lib/hx509/ref/pkcs11.h @@ -0,0 +1,1722 @@ +/* pkcs11.h + Copyright 2006, 2007 g10 Code GmbH + Copyright 2006 Andreas Jellinghaus + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. */ + +/* Please submit changes back to the Scute project at + http://www.scute.org/ (or send them to marcus@g10code.com), so that + they can be picked up by other projects from there as well. */ + +/* This file is a modified implementation of the PKCS #11 standard by + RSA Security Inc. It is mostly a drop-in replacement, with the + following change: + + This header file does not require any macro definitions by the user + (like CK_DEFINE_FUNCTION etc). In fact, it defines those macros + for you (if useful, some are missing, let me know if you need + more). + + There is an additional API available that does comply better to the + GNU coding standard. It can be switched on by defining + CRYPTOKI_GNU before including this header file. For this, the + following changes are made to the specification: + + All structure types are changed to a "struct ck_foo" where CK_FOO + is the type name in PKCS #11. + + All non-structure types are changed to ck_foo_t where CK_FOO is the + lowercase version of the type name in PKCS #11. The basic types + (CK_ULONG et al.) are removed without substitute. + + All members of structures are modified in the following way: Type + indication prefixes are removed, and underscore characters are + inserted before words. Then the result is lowercased. + + Note that function names are still in the original case, as they + need for ABI compatibility. + + CK_FALSE, CK_TRUE and NULL_PTR are removed without substitute. Use + <stdbool.h>. + + If CRYPTOKI_COMPAT is defined before including this header file, + then none of the API changes above take place, and the API is the + one defined by the PKCS #11 standard. */ + +#ifndef PKCS11_H +#define PKCS11_H 1 + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* The version of cryptoki we implement. The revision is changed with + each modification of this file. If you do not use the "official" + version of this file, please consider deleting the revision macro + (you may use a macro with a different name to keep track of your + versions). */ +#define CRYPTOKI_VERSION_MAJOR 2 +#define CRYPTOKI_VERSION_MINOR 30 +#define CRYPTOKI_VERSION_REVISION 0 +#define CRYPTOKI_VERSION_AMENDMENT 0 + + +/* Compatibility interface is default, unless CRYPTOKI_GNU is + given. */ +#ifndef CRYPTOKI_GNU +#ifndef CRYPTOKI_COMPAT +#define CRYPTOKI_COMPAT 1 +#endif +#endif + +/* System dependencies. */ + +#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32) + +/* There is a matching pop below. */ +#pragma pack(push, cryptoki, 1) + +#ifdef CRYPTOKI_EXPORTS +#define CK_SPEC __declspec(dllexport) +#else +#define CK_SPEC __declspec(dllimport) +#endif + +#else + +#if defined(CRYPTOKI_VISIBILITY) && defined(CRYPTOKI_EXPORTS) +#define CK_SPEC __attribute__((visibility("default"))) +#else +#define CK_SPEC +#endif + +#endif + + +#ifdef CRYPTOKI_COMPAT + /* If we are in compatibility mode, switch all exposed names to the + PKCS #11 variant. There are corresponding #undefs below. */ + +#define ck_flags_t CK_FLAGS +#define ck_version _CK_VERSION + +#define ck_info _CK_INFO +#define cryptoki_version cryptokiVersion +#define manufacturer_id manufacturerID +#define library_description libraryDescription +#define library_version libraryVersion + +#define ck_notification_t CK_NOTIFICATION +#define ck_slot_id_t CK_SLOT_ID + +#define ck_slot_info _CK_SLOT_INFO +#define slot_description slotDescription +#define hardware_version hardwareVersion +#define firmware_version firmwareVersion + +#define ck_token_info _CK_TOKEN_INFO +#define serial_number serialNumber +#define max_session_count ulMaxSessionCount +#define session_count ulSessionCount +#define max_rw_session_count ulMaxRwSessionCount +#define rw_session_count ulRwSessionCount +#define max_pin_len ulMaxPinLen +#define min_pin_len ulMinPinLen +#define total_public_memory ulTotalPublicMemory +#define free_public_memory ulFreePublicMemory +#define total_private_memory ulTotalPrivateMemory +#define free_private_memory ulFreePrivateMemory +#define utc_time utcTime + +#define ck_session_handle_t CK_SESSION_HANDLE +#define ck_user_type_t CK_USER_TYPE +#define ck_state_t CK_STATE + +#define ck_session_info _CK_SESSION_INFO +#define slot_id slotID +#define device_error ulDeviceError + +#define ck_object_handle_t CK_OBJECT_HANDLE +#define ck_object_class_t CK_OBJECT_CLASS +#define ck_hw_feature_type_t CK_HW_FEATURE_TYPE +#define ck_key_type_t CK_KEY_TYPE +#define ck_certificate_type_t CK_CERTIFICATE_TYPE +#define ck_attribute_type_t CK_ATTRIBUTE_TYPE + +#define ck_attribute _CK_ATTRIBUTE +#define value pValue +#define value_len ulValueLen + +#define ck_date _CK_DATE + +#define ck_mechanism_type_t CK_MECHANISM_TYPE + +#define ck_mechanism _CK_MECHANISM +#define parameter pParameter +#define parameter_len ulParameterLen + +#define ck_mechanism_info _CK_MECHANISM_INFO +#define min_key_size ulMinKeySize +#define max_key_size ulMaxKeySize + +#define hash_alg hashAlg +#define source_data pSourceData +#define source_data_len ulSourceDataLen + +#define slen sLen + +#define ck_ec_kdf_type_t CK_EC_KDF_TYPE + +#define shared_data_len ulSharedDataLen +#define shared_data pSharedData +#define public_data_len ulPublicDataLen +#define public_data pPublicData + +#define private_data_len ulPrivateDataLen +#define private_data hPrivateData +#define public_data_len2 ulPublicDataLen2 +#define public_data2 pPublicData2 + +#define public_key publicKey + +#define ck_x9_42_dh_kdf_type_t CK_X9_42_DH_KDF_TYPE + +#define other_info_len ulOtherInfoLen +#define other_info pOtherInfo + +#define data pData +#define len ulLen + +#define ck_rv_t CK_RV +#define ck_notify_t CK_NOTIFY + +#define ck_function_list _CK_FUNCTION_LIST + +#define ck_createmutex_t CK_CREATEMUTEX +#define ck_destroymutex_t CK_DESTROYMUTEX +#define ck_lockmutex_t CK_LOCKMUTEX +#define ck_unlockmutex_t CK_UNLOCKMUTEX + +#define ck_c_initialize_args _CK_C_INITIALIZE_ARGS +#define create_mutex CreateMutex +#define destroy_mutex DestroyMutex +#define lock_mutex LockMutex +#define unlock_mutex UnlockMutex +#define reserved pReserved + +#endif /* CRYPTOKI_COMPAT */ + + + +typedef unsigned long ck_flags_t; + +struct ck_version +{ + unsigned char major; + unsigned char minor; +}; + + +struct ck_info +{ + struct ck_version cryptoki_version; + unsigned char manufacturer_id[32]; + ck_flags_t flags; + unsigned char library_description[32]; + struct ck_version library_version; +}; + + +typedef unsigned long ck_notification_t; + +#define CKN_SURRENDER (0) +#define CKN_OTP_CHANGED (1) + +typedef unsigned long ck_slot_id_t; + + +struct ck_slot_info +{ + unsigned char slot_description[64]; + unsigned char manufacturer_id[32]; + ck_flags_t flags; + struct ck_version hardware_version; + struct ck_version firmware_version; +}; + + +#define CKF_TOKEN_PRESENT (1 << 0) +#define CKF_REMOVABLE_DEVICE (1 << 1) +#define CKF_HW_SLOT (1 << 2) +#define CKF_ARRAY_ATTRIBUTE (1 << 30) + + +struct ck_token_info +{ + unsigned char label[32]; + unsigned char manufacturer_id[32]; + unsigned char model[16]; + unsigned char serial_number[16]; + ck_flags_t flags; + unsigned long max_session_count; + unsigned long session_count; + unsigned long max_rw_session_count; + unsigned long rw_session_count; + unsigned long max_pin_len; + unsigned long min_pin_len; + unsigned long total_public_memory; + unsigned long free_public_memory; + unsigned long total_private_memory; + unsigned long free_private_memory; + struct ck_version hardware_version; + struct ck_version firmware_version; + unsigned char utc_time[16]; +}; + + +#define CKF_RNG (1 << 0) +#define CKF_WRITE_PROTECTED (1 << 1) +#define CKF_LOGIN_REQUIRED (1 << 2) +#define CKF_USER_PIN_INITIALIZED (1 << 3) +#define CKF_RESTORE_KEY_NOT_NEEDED (1 << 5) +#define CKF_CLOCK_ON_TOKEN (1 << 6) +#define CKF_PROTECTED_AUTHENTICATION_PATH (1 << 8) +#define CKF_DUAL_CRYPTO_OPERATIONS (1 << 9) +#define CKF_TOKEN_INITIALIZED (1 << 10) +#define CKF_SECONDARY_AUTHENTICATION (1 << 11) +#define CKF_USER_PIN_COUNT_LOW (1 << 16) +#define CKF_USER_PIN_FINAL_TRY (1 << 17) +#define CKF_USER_PIN_LOCKED (1 << 18) +#define CKF_USER_PIN_TO_BE_CHANGED (1 << 19) +#define CKF_SO_PIN_COUNT_LOW (1 << 20) +#define CKF_SO_PIN_FINAL_TRY (1 << 21) +#define CKF_SO_PIN_LOCKED (1 << 22) +#define CKF_SO_PIN_TO_BE_CHANGED (1 << 23) +#define CKF_ERROR_STATE (1 << 24) + +#define CK_UNAVAILABLE_INFORMATION ((unsigned long) -1) +#define CK_EFFECTIVELY_INFINITE (0) + + +typedef unsigned long ck_session_handle_t; + +#define CK_INVALID_HANDLE (0) + + +typedef unsigned long ck_user_type_t; + +#define CKU_SO (0) +#define CKU_USER (1) +#define CKU_CONTEXT_SPECIFIC (2) + + +typedef unsigned long ck_state_t; + +#define CKS_RO_PUBLIC_SESSION (0) +#define CKS_RO_USER_FUNCTIONS (1) +#define CKS_RW_PUBLIC_SESSION (2) +#define CKS_RW_USER_FUNCTIONS (3) +#define CKS_RW_SO_FUNCTIONS (4) + + +struct ck_session_info +{ + ck_slot_id_t slot_id; + ck_state_t state; + ck_flags_t flags; + unsigned long device_error; +}; + +#define CKF_RW_SESSION (1 << 1) +#define CKF_SERIAL_SESSION (1 << 2) + + +typedef unsigned long ck_object_handle_t; + + +typedef unsigned long ck_object_class_t; + +#define CKO_DATA (0) +#define CKO_CERTIFICATE (1) +#define CKO_PUBLIC_KEY (2) +#define CKO_PRIVATE_KEY (3) +#define CKO_SECRET_KEY (4) +#define CKO_HW_FEATURE (5) +#define CKO_DOMAIN_PARAMETERS (6) +#define CKO_MECHANISM (7) +#define CKO_OTP_KEY (8) +#define CKO_VENDOR_DEFINED ((unsigned long) (1ul << 31)) + + +typedef unsigned long ck_hw_feature_type_t; + +#define CKH_MONOTONIC_COUNTER (1) +#define CKH_CLOCK (2) +#define CKH_USER_INTERFACE (3) +#define CKH_VENDOR_DEFINED ((unsigned long) (1ul << 31)) + + +typedef unsigned long ck_key_type_t; + +#define CKK_RSA (0) +#define CKK_DSA (1) +#define CKK_DH (2) +#define CKK_ECDSA (3) +#define CKK_EC (3) +#define CKK_X9_42_DH (4) +#define CKK_KEA (5) +#define CKK_GENERIC_SECRET (0x10) +#define CKK_RC2 (0x11) +#define CKK_RC4 (0x12) +#define CKK_DES (0x13) +#define CKK_DES2 (0x14) +#define CKK_DES3 (0x15) +#define CKK_CAST (0x16) +#define CKK_CAST3 (0x17) +#define CKK_CAST5 (0x18) +#define CKK_CAST128 (0x18) +#define CKK_RC5 (0x19) +#define CKK_IDEA (0x1a) +#define CKK_SKIPJACK (0x1b) +#define CKK_BATON (0x1c) +#define CKK_JUNIPER (0x1d) +#define CKK_CDMF (0x1e) +#define CKK_AES (0x1f) +#define CKK_BLOWFISH (0x20) +#define CKK_TWOFISH (0x21) +#define CKK_SECURID (0x22) +#define CKK_HOTP (0x23) +#define CKK_ACTI (0x24) +#define CKK_CAMELLIA (0x25) +#define CKK_ARIA (0x26) +#define CKK_MD5_HMAC (0x27) +#define CKK_SHA_1_HMAC (0x28) +#define CKK_RIPEMD128_HMAC (0x29) +#define CKK_RIPEMD160_HMAC (0x2A) +#define CKK_SHA256_HMAC (0x2B) +#define CKK_SHA384_HMAC (0x2C) +#define CKK_SHA512_HMAC (0x2D) +#define CKK_SHA224_HMAC (0x2E) +#define CKK_SEED (0x2F) +#define CKK_GOSTR3410 (0x30) +#define CKK_GOSTR3411 (0x31) +#define CKK_GOST28147 (0x32) +#define CKK_VENDOR_DEFINED ((unsigned long) (1ul << 31)) + + +typedef unsigned long ck_certificate_type_t; + +#define CKC_X_509 (0) +#define CKC_X_509_ATTR_CERT (1) +#define CKC_WTLS (2) +#define CKC_VENDOR_DEFINED ((unsigned long) (1ul << 31)) +#define CKC_OPENPGP (CKC_VENDOR_DEFINED|0x00504750) + +#define CK_OTP_FORMAT_DECIMAL (0) +#define CK_OTP_FORMAT_HEXADECIMAL (1) +#define CK_OTP_FORMAT_ALPHANUMERIC (2) +#define CK_OTP_FORMAT_BINARY (3) + +#define CK_OTP_PARAM_IGNORED (0) +#define CK_OTP_PARAM_OPTIONAL (1) +#define CK_OTP_PARAM_MANDATORY (2) + +typedef unsigned long ck_attribute_type_t; + +#define CKA_CLASS (0) +#define CKA_TOKEN (1) +#define CKA_PRIVATE (2) +#define CKA_LABEL (3) +#define CKA_APPLICATION (0x10) +#define CKA_VALUE (0x11) +#define CKA_OBJECT_ID (0x12) +#define CKA_CERTIFICATE_TYPE (0x80) +#define CKA_ISSUER (0x81) +#define CKA_SERIAL_NUMBER (0x82) +#define CKA_AC_ISSUER (0x83) +#define CKA_OWNER (0x84) +#define CKA_ATTR_TYPES (0x85) +#define CKA_TRUSTED (0x86) +#define CKA_CERTIFICATE_CATEGORY (0x87) +#define CKA_JAVA_MIDP_SECURITY_DOMAIN (0x88) +#define CKA_URL (0x89) +#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY (0x8a) +#define CKA_HASH_OF_ISSUER_PUBLIC_KEY (0x8b) +#define CKA_NAME_HASH_ALGORITHM (0x8c) +#define CKA_CHECK_VALUE (0x90) +#define CKA_KEY_TYPE (0x100) +#define CKA_SUBJECT (0x101) +#define CKA_ID (0x102) +#define CKA_SENSITIVE (0x103) +#define CKA_ENCRYPT (0x104) +#define CKA_DECRYPT (0x105) +#define CKA_WRAP (0x106) +#define CKA_UNWRAP (0x107) +#define CKA_SIGN (0x108) +#define CKA_SIGN_RECOVER (0x109) +#define CKA_VERIFY (0x10a) +#define CKA_VERIFY_RECOVER (0x10b) +#define CKA_DERIVE (0x10c) +#define CKA_START_DATE (0x110) +#define CKA_END_DATE (0x111) +#define CKA_MODULUS (0x120) +#define CKA_MODULUS_BITS (0x121) +#define CKA_PUBLIC_EXPONENT (0x122) +#define CKA_PRIVATE_EXPONENT (0x123) +#define CKA_PRIME_1 (0x124) +#define CKA_PRIME_2 (0x125) +#define CKA_EXPONENT_1 (0x126) +#define CKA_EXPONENT_2 (0x127) +#define CKA_COEFFICIENT (0x128) +#define CKA_PRIME (0x130) +#define CKA_SUBPRIME (0x131) +#define CKA_BASE (0x132) +#define CKA_PRIME_BITS (0x133) +#define CKA_SUB_PRIME_BITS (0x134) +#define CKA_SUBPRIME_BITS (0x134) +#define CKA_VALUE_BITS (0x160) +#define CKA_VALUE_LEN (0x161) +#define CKA_EXTRACTABLE (0x162) +#define CKA_LOCAL (0x163) +#define CKA_NEVER_EXTRACTABLE (0x164) +#define CKA_ALWAYS_SENSITIVE (0x165) +#define CKA_KEY_GEN_MECHANISM (0x166) +#define CKA_MODIFIABLE (0x170) +#define CKA_COPYABLE (0x171) +#define CKA_ECDSA_PARAMS (0x180) +#define CKA_EC_PARAMS (0x180) +#define CKA_EC_POINT (0x181) +#define CKA_SECONDARY_AUTH (0x200) +#define CKA_AUTH_PIN_FLAGS (0x201) +#define CKA_ALWAYS_AUTHENTICATE (0x202) +#define CKA_WRAP_WITH_TRUSTED (0x210) +#define CKA_OTP_FORMAT (0x220) +#define CKA_OTP_LENGTH (0x221) +#define CKA_OTP_TIME_INTERVAL (0x222) +#define CKA_OTP_USER_FRIENDLY_MODE (0x223) +#define CKA_OTP_CHALLENGE_REQUIREMENT (0x224) +#define CKA_OTP_TIME_REQUIREMENT (0x225) +#define CKA_OTP_COUNTER_REQUIREMENT (0x226) +#define CKA_OTP_PIN_REQUIREMENT (0x227) +#define CKA_OTP_COUNTER (0x22E) +#define CKA_OTP_TIME (0x22F) +#define CKA_OTP_USER_IDENTIFIER (0x22A) +#define CKA_OTP_SERVICE_IDENTIFIER (0x22B) +#define CKA_OTP_SERVICE_LOGO (0x22C) +#define CKA_OTP_SERVICE_LOGO_TYPE (0x22D) +#define CKA_GOSTR3410_PARAMS (0x250) +#define CKA_GOSTR3411_PARAMS (0x251) +#define CKA_GOST28147_PARAMS (0x252) +#define CKA_HW_FEATURE_TYPE (0x300) +#define CKA_RESET_ON_INIT (0x301) +#define CKA_HAS_RESET (0x302) +#define CKA_PIXEL_X (0x400) +#define CKA_PIXEL_Y (0x401) +#define CKA_RESOLUTION (0x402) +#define CKA_CHAR_ROWS (0x403) +#define CKA_CHAR_COLUMNS (0x404) +#define CKA_COLOR (0x405) +#define CKA_BITS_PER_PIXEL (0x406) +#define CKA_CHAR_SETS (0x480) +#define CKA_ENCODING_METHODS (0x481) +#define CKA_MIME_TYPES (0x482) +#define CKA_MECHANISM_TYPE (0x500) +#define CKA_REQUIRED_CMS_ATTRIBUTES (0x501) +#define CKA_DEFAULT_CMS_ATTRIBUTES (0x502) +#define CKA_SUPPORTED_CMS_ATTRIBUTES (0x503) +#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x211) +#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x212) +#define CKA_DERIVE_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x213) +#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE | 0x600) +#define CKA_VENDOR_DEFINED ((unsigned long) (1ul << 31)) + + +struct ck_attribute +{ + ck_attribute_type_t type; + void *value; + unsigned long value_len; +}; + + +struct ck_date +{ + unsigned char year[4]; + unsigned char month[2]; + unsigned char day[2]; +}; + + +typedef unsigned long ck_mechanism_type_t; + +#define CKM_RSA_PKCS_KEY_PAIR_GEN (0) +#define CKM_RSA_PKCS (1) +#define CKM_RSA_9796 (2) +#define CKM_RSA_X_509 (3) +#define CKM_MD2_RSA_PKCS (4) +#define CKM_MD5_RSA_PKCS (5) +#define CKM_SHA1_RSA_PKCS (6) +#define CKM_RIPEMD128_RSA_PKCS (7) +#define CKM_RIPEMD160_RSA_PKCS (8) +#define CKM_RSA_PKCS_OAEP (9) +#define CKM_RSA_X9_31_KEY_PAIR_GEN (0xa) +#define CKM_RSA_X9_31 (0xb) +#define CKM_SHA1_RSA_X9_31 (0xc) +#define CKM_RSA_PKCS_PSS (0xd) +#define CKM_SHA1_RSA_PKCS_PSS (0xe) +#define CKM_DSA_KEY_PAIR_GEN (0x10) +#define CKM_DSA (0x11) +#define CKM_DSA_SHA1 (0x12) +#define CKM_DSA_SHA224 (0x13) +#define CKM_DSA_SHA256 (0x14) +#define CKM_DSA_SHA384 (0x15) +#define CKM_DSA_SHA512 (0x16) +#define CKM_DH_PKCS_KEY_PAIR_GEN (0x20) +#define CKM_DH_PKCS_DERIVE (0x21) +#define CKM_X9_42_DH_KEY_PAIR_GEN (0x30) +#define CKM_X9_42_DH_DERIVE (0x31) +#define CKM_X9_42_DH_HYBRID_DERIVE (0x32) +#define CKM_X9_42_MQV_DERIVE (0x33) +#define CKM_SHA256_RSA_PKCS (0x40) +#define CKM_SHA384_RSA_PKCS (0x41) +#define CKM_SHA512_RSA_PKCS (0x42) +#define CKM_SHA256_RSA_PKCS_PSS (0x43) +#define CKM_SHA384_RSA_PKCS_PSS (0x44) +#define CKM_SHA512_RSA_PKCS_PSS (0x45) +#define CKM_SHA224_RSA_PKCS (0x46) +#define CKM_SHA224_RSA_PKCS_PSS (0x47) +#define CKM_RC2_KEY_GEN (0x100) +#define CKM_RC2_ECB (0x101) +#define CKM_RC2_CBC (0x102) +#define CKM_RC2_MAC (0x103) +#define CKM_RC2_MAC_GENERAL (0x104) +#define CKM_RC2_CBC_PAD (0x105) +#define CKM_RC4_KEY_GEN (0x110) +#define CKM_RC4 (0x111) +#define CKM_DES_KEY_GEN (0x120) +#define CKM_DES_ECB (0x121) +#define CKM_DES_CBC (0x122) +#define CKM_DES_MAC (0x123) +#define CKM_DES_MAC_GENERAL (0x124) +#define CKM_DES_CBC_PAD (0x125) +#define CKM_DES2_KEY_GEN (0x130) +#define CKM_DES3_KEY_GEN (0x131) +#define CKM_DES3_ECB (0x132) +#define CKM_DES3_CBC (0x133) +#define CKM_DES3_MAC (0x134) +#define CKM_DES3_MAC_GENERAL (0x135) +#define CKM_DES3_CBC_PAD (0x136) +#define CKM_DES3_CMAC_GENERAL (0x137) +#define CKM_DES3_CMAC (0x138) +#define CKM_CDMF_KEY_GEN (0x140) +#define CKM_CDMF_ECB (0x141) +#define CKM_CDMF_CBC (0x142) +#define CKM_CDMF_MAC (0x143) +#define CKM_CDMF_MAC_GENERAL (0x144) +#define CKM_CDMF_CBC_PAD (0x145) +#define CKM_DES_OFB64 (0x150) +#define CKM_DES_OFB8 (0x151) +#define CKM_DES_CFB64 (0x152) +#define CKM_DES_CFB8 (0x153) +#define CKM_MD2 (0x200) +#define CKM_MD2_HMAC (0x201) +#define CKM_MD2_HMAC_GENERAL (0x202) +#define CKM_MD5 (0x210) +#define CKM_MD5_HMAC (0x211) +#define CKM_MD5_HMAC_GENERAL (0x212) +#define CKM_SHA_1 (0x220) +#define CKM_SHA_1_HMAC (0x221) +#define CKM_SHA_1_HMAC_GENERAL (0x222) +#define CKM_RIPEMD128 (0x230) +#define CKM_RIPEMD128_HMAC (0x231) +#define CKM_RIPEMD128_HMAC_GENERAL (0x232) +#define CKM_RIPEMD160 (0x240) +#define CKM_RIPEMD160_HMAC (0x241) +#define CKM_RIPEMD160_HMAC_GENERAL (0x242) +#define CKM_SHA256 (0x250) +#define CKM_SHA256_HMAC (0x251) +#define CKM_SHA256_HMAC_GENERAL (0x252) +#define CKM_SHA224 (0x255) +#define CKM_SHA224_HMAC (0x256) +#define CKM_SHA224_HMAC_GENERAL (0x257) +#define CKM_SHA384 (0x260) +#define CKM_SHA384_HMAC (0x261) +#define CKM_SHA384_HMAC_GENERAL (0x262) +#define CKM_SHA512 (0x270) +#define CKM_SHA512_HMAC (0x271) +#define CKM_SHA512_HMAC_GENERAL (0x272) +#define CKM_SECURID_KEY_GEN (0x280) +#define CKM_SECURID (0x282) +#define CKM_HOTP_KEY_GEN (0x290) +#define CKM_HOTP (0x291) +#define CKM_ACTI (0x2A0) +#define CKM_ACTI_KEY_GEN (0x2A1) +#define CKM_CAST_KEY_GEN (0x300) +#define CKM_CAST_ECB (0x301) +#define CKM_CAST_CBC (0x302) +#define CKM_CAST_MAC (0x303) +#define CKM_CAST_MAC_GENERAL (0x304) +#define CKM_CAST_CBC_PAD (0x305) +#define CKM_CAST3_KEY_GEN (0x310) +#define CKM_CAST3_ECB (0x311) +#define CKM_CAST3_CBC (0x312) +#define CKM_CAST3_MAC (0x313) +#define CKM_CAST3_MAC_GENERAL (0x314) +#define CKM_CAST3_CBC_PAD (0x315) +#define CKM_CAST5_KEY_GEN (0x320) +#define CKM_CAST128_KEY_GEN (0x320) +#define CKM_CAST5_ECB (0x321) +#define CKM_CAST128_ECB (0x321) +#define CKM_CAST5_CBC (0x322) +#define CKM_CAST128_CBC (0x322) +#define CKM_CAST5_MAC (0x323) +#define CKM_CAST128_MAC (0x323) +#define CKM_CAST5_MAC_GENERAL (0x324) +#define CKM_CAST128_MAC_GENERAL (0x324) +#define CKM_CAST5_CBC_PAD (0x325) +#define CKM_CAST128_CBC_PAD (0x325) +#define CKM_RC5_KEY_GEN (0x330) +#define CKM_RC5_ECB (0x331) +#define CKM_RC5_CBC (0x332) +#define CKM_RC5_MAC (0x333) +#define CKM_RC5_MAC_GENERAL (0x334) +#define CKM_RC5_CBC_PAD (0x335) +#define CKM_IDEA_KEY_GEN (0x340) +#define CKM_IDEA_ECB (0x341) +#define CKM_IDEA_CBC (0x342) +#define CKM_IDEA_MAC (0x343) +#define CKM_IDEA_MAC_GENERAL (0x344) +#define CKM_IDEA_CBC_PAD (0x345) +#define CKM_GENERIC_SECRET_KEY_GEN (0x350) +#define CKM_CONCATENATE_BASE_AND_KEY (0x360) +#define CKM_CONCATENATE_BASE_AND_DATA (0x362) +#define CKM_CONCATENATE_DATA_AND_BASE (0x363) +#define CKM_XOR_BASE_AND_DATA (0x364) +#define CKM_EXTRACT_KEY_FROM_KEY (0x365) +#define CKM_SSL3_PRE_MASTER_KEY_GEN (0x370) +#define CKM_SSL3_MASTER_KEY_DERIVE (0x371) +#define CKM_SSL3_KEY_AND_MAC_DERIVE (0x372) +#define CKM_SSL3_MASTER_KEY_DERIVE_DH (0x373) +#define CKM_TLS_PRE_MASTER_KEY_GEN (0x374) +#define CKM_TLS_MASTER_KEY_DERIVE (0x375) +#define CKM_TLS_KEY_AND_MAC_DERIVE (0x376) +#define CKM_TLS_MASTER_KEY_DERIVE_DH (0x377) +#define CKM_TLS_PRF (0x378) +#define CKM_SSL3_MD5_MAC (0x380) +#define CKM_SSL3_SHA1_MAC (0x381) +#define CKM_MD5_KEY_DERIVATION (0x390) +#define CKM_MD2_KEY_DERIVATION (0x391) +#define CKM_SHA1_KEY_DERIVATION (0x392) +#define CKM_SHA256_KEY_DERIVATION (0x393) +#define CKM_SHA384_KEY_DERIVATION (0x394) +#define CKM_SHA512_KEY_DERIVATION (0x395) +#define CKM_SHA224_KEY_DERIVATION (0x396) +#define CKM_PBE_MD2_DES_CBC (0x3a0) +#define CKM_PBE_MD5_DES_CBC (0x3a1) +#define CKM_PBE_MD5_CAST_CBC (0x3a2) +#define CKM_PBE_MD5_CAST3_CBC (0x3a3) +#define CKM_PBE_MD5_CAST5_CBC (0x3a4) +#define CKM_PBE_MD5_CAST128_CBC (0x3a4) +#define CKM_PBE_SHA1_CAST5_CBC (0x3a5) +#define CKM_PBE_SHA1_CAST128_CBC (0x3a5) +#define CKM_PBE_SHA1_RC4_128 (0x3a6) +#define CKM_PBE_SHA1_RC4_40 (0x3a7) +#define CKM_PBE_SHA1_DES3_EDE_CBC (0x3a8) +#define CKM_PBE_SHA1_DES2_EDE_CBC (0x3a9) +#define CKM_PBE_SHA1_RC2_128_CBC (0x3aa) +#define CKM_PBE_SHA1_RC2_40_CBC (0x3ab) +#define CKM_PKCS5_PBKD2 (0x3b0) +#define CKM_PBA_SHA1_WITH_SHA1_HMAC (0x3c0) +#define CKM_WTLS_PRE_MASTER_KEY_GEN (0x3d0) +#define CKM_WTLS_MASTER_KEY_DERIVE (0x3d1) +#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC (0x3d2) +#define CKM_WTLS_PRF (0x3d3) +#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE (0x3d4) +#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE (0x3d5) +#define CKM_KEY_WRAP_LYNKS (0x400) +#define CKM_KEY_WRAP_SET_OAEP (0x401) +#define CKM_CMS_SIG (0x500) +#define CKM_KIP_DERIVE (0x510) +#define CKM_KIP_WRAP (0x511) +#define CKM_KIP_MAC (0x512) +#define CKM_CAMELLIA_KEY_GEN (0x550) +#define CKM_CAMELLIA_ECB (0x551) +#define CKM_CAMELLIA_CBC (0x552) +#define CKM_CAMELLIA_MAC (0x553) +#define CKM_CAMELLIA_MAC_GENERAL (0x554) +#define CKM_CAMELLIA_CBC_PAD (0x555) +#define CKM_CAMELLIA_ECB_ENCRYPT_DATA (0x556) +#define CKM_CAMELLIA_CBC_ENCRYPT_DATA (0x557) +#define CKM_CAMELLIA_CTR (0x558) +#define CKM_ARIA_KEY_GEN (0x560) +#define CKM_ARIA_ECB (0x561) +#define CKM_ARIA_CBC (0x562) +#define CKM_ARIA_MAC (0x563) +#define CKM_ARIA_MAC_GENERAL (0x564) +#define CKM_ARIA_CBC_PAD (0x565) +#define CKM_ARIA_ECB_ENCRYPT_DATA (0x566) +#define CKM_ARIA_CBC_ENCRYPT_DATA (0x567) +#define CKM_SEED_KEY_GEN (0x650) +#define CKM_SEED_ECB (0x651) +#define CKM_SEED_CBC (0x652) +#define CKM_SEED_MAC (0x653) +#define CKM_SEED_MAC_GENERAL (0x654) +#define CKM_SEED_CBC_PAD (0x655) +#define CKM_SEED_ECB_ENCRYPT_DATA (0x656) +#define CKM_SEED_CBC_ENCRYPT_DATA (0x657) +#define CKM_SKIPJACK_KEY_GEN (0x1000) +#define CKM_SKIPJACK_ECB64 (0x1001) +#define CKM_SKIPJACK_CBC64 (0x1002) +#define CKM_SKIPJACK_OFB64 (0x1003) +#define CKM_SKIPJACK_CFB64 (0x1004) +#define CKM_SKIPJACK_CFB32 (0x1005) +#define CKM_SKIPJACK_CFB16 (0x1006) +#define CKM_SKIPJACK_CFB8 (0x1007) +#define CKM_SKIPJACK_WRAP (0x1008) +#define CKM_SKIPJACK_PRIVATE_WRAP (0x1009) +#define CKM_SKIPJACK_RELAYX (0x100a) +#define CKM_KEA_KEY_PAIR_GEN (0x1010) +#define CKM_KEA_KEY_DERIVE (0x1011) +#define CKM_FORTEZZA_TIMESTAMP (0x1020) +#define CKM_BATON_KEY_GEN (0x1030) +#define CKM_BATON_ECB128 (0x1031) +#define CKM_BATON_ECB96 (0x1032) +#define CKM_BATON_CBC128 (0x1033) +#define CKM_BATON_COUNTER (0x1034) +#define CKM_BATON_SHUFFLE (0x1035) +#define CKM_BATON_WRAP (0x1036) +#define CKM_ECDSA_KEY_PAIR_GEN (0x1040) +#define CKM_EC_KEY_PAIR_GEN (0x1040) +#define CKM_ECDSA (0x1041) +#define CKM_ECDSA_SHA1 (0x1042) +#define CKM_ECDSA_SHA224 (0x1043) +#define CKM_ECDSA_SHA256 (0x1044) +#define CKM_ECDSA_SHA384 (0x1045) +#define CKM_ECDSA_SHA512 (0x1046) +#define CKM_ECDH1_DERIVE (0x1050) +#define CKM_ECDH1_COFACTOR_DERIVE (0x1051) +#define CKM_ECMQV_DERIVE (0x1052) +#define CKM_JUNIPER_KEY_GEN (0x1060) +#define CKM_JUNIPER_ECB128 (0x1061) +#define CKM_JUNIPER_CBC128 (0x1062) +#define CKM_JUNIPER_COUNTER (0x1063) +#define CKM_JUNIPER_SHUFFLE (0x1064) +#define CKM_JUNIPER_WRAP (0x1065) +#define CKM_FASTHASH (0x1070) +#define CKM_AES_KEY_GEN (0x1080) +#define CKM_AES_ECB (0x1081) +#define CKM_AES_CBC (0x1082) +#define CKM_AES_MAC (0x1083) +#define CKM_AES_MAC_GENERAL (0x1084) +#define CKM_AES_CBC_PAD (0x1085) +#define CKM_AES_CTR (0x1086) +#define CKM_AES_GCM (0x1087) +#define CKM_AES_CCM (0x1088) +#define CKM_AES_CTS (0x1089) +#define CKM_AES_CMAC (0x108a) +#define CKM_AES_CMAC_GENERAL (0x108b) +#define CKM_BLOWFISH_KEY_GEN (0x1090) +#define CKM_BLOWFISH_CBC (0x1091) +#define CKM_TWOFISH_KEY_GEN (0x1092) +#define CKM_TWOFISH_CBC (0x1093) +#define CKM_BLOWFISH_CBC_PAD (0x1094) +#define CKM_TWOFISH_CBC_PAD (0x1095) +#define CKM_DES_ECB_ENCRYPT_DATA (0x1100) +#define CKM_DES_CBC_ENCRYPT_DATA (0x1101) +#define CKM_DES3_ECB_ENCRYPT_DATA (0x1102) +#define CKM_DES3_CBC_ENCRYPT_DATA (0x1103) +#define CKM_AES_ECB_ENCRYPT_DATA (0x1104) +#define CKM_AES_CBC_ENCRYPT_DATA (0x1105) +#define CKM_GOSTR3410_KEY_PAIR_GEN (0x1200) +#define CKM_GOSTR3410 (0x1201) +#define CKM_GOSTR3410_WITH_GOSTR3411 (0x1202) +#define CKM_GOSTR3410_KEY_WRAP (0x1203) +#define CKM_GOSTR3410_DERIVE (0x1204) +#define CKM_GOSTR3411 (0x1210) +#define CKM_GOSTR3411_HMAC (0x1211) +#define CKM_GOST28147_KEY_GEN (0x1220) +#define CKM_GOST28147_ECB (0x1221) +#define CKM_GOST28147 (0x1222) +#define CKM_GOST28147_MAC (0x1223) +#define CKM_GOST28147_KEY_WRAP (0x1224) +#define CKM_DSA_PARAMETER_GEN (0x2000) +#define CKM_DH_PKCS_PARAMETER_GEN (0x2001) +#define CKM_X9_42_DH_PARAMETER_GEN (0x2002) +#define CKM_AES_OFB (0x2104) +#define CKM_AES_CFB64 (0x2105) +#define CKM_AES_CFB8 (0x2106) +#define CKM_AES_CFB128 (0x2107) +#define CKM_AES_KEY_WRAP (0x2109) +#define CKM_AES_KEY_WRAP_PAD (0x210a) +#define CKM_RSA_PKCS_TPM_1_1 (0x4001) +#define CKM_RSA_PKCS_OAEPTPM_1_1 (0x4002) +#define CKM_VENDOR_DEFINED ((unsigned long) (1ul << 31)) + + +struct ck_mechanism +{ + ck_mechanism_type_t mechanism; + void *parameter; + unsigned long parameter_len; +}; + + +struct ck_mechanism_info +{ + unsigned long min_key_size; + unsigned long max_key_size; + ck_flags_t flags; +}; + +#define CKF_HW (1 << 0) +#define CKF_ENCRYPT (1 << 8) +#define CKF_DECRYPT (1 << 9) +#define CKF_DIGEST (1 << 10) +#define CKF_SIGN (1 << 11) +#define CKF_SIGN_RECOVER (1 << 12) +#define CKF_VERIFY (1 << 13) +#define CKF_VERIFY_RECOVER (1 << 14) +#define CKF_GENERATE (1 << 15) +#define CKF_GENERATE_KEY_PAIR (1 << 16) +#define CKF_WRAP (1 << 17) +#define CKF_UNWRAP (1 << 18) +#define CKF_DERIVE (1 << 19) +#define CKF_EC_F_P (1 << 20) +#define CKF_EC_F_2M (1 << 21) +#define CKF_EC_ECPARAMETERS (1 << 22) +#define CKF_EC_NAMEDCURVE (1 << 23) +#define CKF_EC_UNCOMPRESS (1 << 24) +#define CKF_EC_COMPRESS (1 << 25) +#define CKF_EXTENSION ((unsigned long) (1ul << 31)) + + +/* The following MGFs are defined */ +#define CKG_MGF1_SHA1 (0x00000001) +#define CKG_MGF1_SHA256 (0x00000002) +#define CKG_MGF1_SHA384 (0x00000003) +#define CKG_MGF1_SHA512 (0x00000004) +#define CKG_MGF1_SHA224 (0x00000005) + +#define CKZ_DATA_SPECIFIED (0x00000001) + +struct ck_rsa_pkcs_oaep_params { + ck_mechanism_type_t hash_alg; + unsigned long mgf; + unsigned long source; + void *source_data; + unsigned long source_data_len; +}; + +struct ck_rsa_pkcs_pss_params { + ck_mechanism_type_t hash_alg; + unsigned long mgf; + unsigned long slen; +}; + +typedef unsigned long ck_ec_kdf_type_t; + +/* The following EC Key Derivation Functions are defined */ +#define CKD_NULL (0x00000001) +#define CKD_SHA1_KDF (0x00000002) + +struct ck_ecdh1_derive_params { + ck_ec_kdf_type_t kdf; + unsigned long shared_data_len; + unsigned char *shared_data; + unsigned long public_data_len; + unsigned char *public_data; +}; + +struct ck_ecdh2_derive_params { + ck_ec_kdf_type_t kdf; + unsigned long shared_data_len; + unsigned char *shared_data; + unsigned long public_data_len; + unsigned char *public_data; + unsigned long private_data_len; + ck_object_handle_t private_data; + unsigned long public_data_len2; + unsigned char *public_data2; +}; + +struct ck_ecmqv_derive_params { + ck_ec_kdf_type_t kdf; + unsigned long shared_data_len; + unsigned char *shared_data; + unsigned long public_data_len; + unsigned char *public_data; + unsigned long private_data_len; + ck_object_handle_t private_data; + unsigned long public_data_len2; + unsigned char *public_data2; + ck_object_handle_t public_key; +}; + +typedef unsigned long ck_x9_42_dh_kdf_type_t; + +/* The following X9.42 DH key derivation functions are defined */ +#define CKD_SHA1_KDF_ASN1 (0x00000003) +#define CKD_SHA1_KDF_CONCATENATE (0x00000004) +#define CKD_SHA224_KDF (0x00000005) +#define CKD_SHA256_KDF (0x00000006) +#define CKD_SHA384_KDF (0x00000007) +#define CKD_SHA512_KDF (0x00000008) +#define CKD_CPDIVERSIFY_KDF (0x00000009) + +struct ck_x9_42_dh1_derive_params { + ck_x9_42_dh_kdf_type_t kdf; + unsigned long other_info_len; + unsigned char *other_info; + unsigned long public_data_len; + unsigned char *public_data; +}; + +struct ck_x9_42_dh2_derive_params { + ck_x9_42_dh_kdf_type_t kdf; + unsigned long other_info_len; + unsigned char *other_info; + unsigned long public_data_len; + unsigned char *public_data; + unsigned long private_data_len; + ck_object_handle_t private_data; + unsigned long public_data_len2; + unsigned char *public_data2; +}; + +struct ck_x9_42_mqv_derive_params { + ck_x9_42_dh_kdf_type_t kdf; + unsigned long other_info_len; + unsigned char *other_info; + unsigned long public_data_len; + unsigned char *public_data; + unsigned long private_data_len; + ck_object_handle_t private_data; + unsigned long public_data_len2; + unsigned char *public_data2; + ck_object_handle_t public_key; +}; + +struct ck_des_cbc_encrypt_data_params { + unsigned char iv[8]; + unsigned char *data; + unsigned long length; +}; + +struct ck_aes_cbc_encrypt_data_params { + unsigned char iv[16]; + unsigned char *data; + unsigned long length; +}; + +struct ck_key_derivation_string_data { + unsigned char *data; + unsigned long len; +}; + +/* Flags for C_WaitForSlotEvent. */ +#define CKF_DONT_BLOCK (1) + + +typedef unsigned long ck_rv_t; + + +typedef ck_rv_t (*ck_notify_t) (ck_session_handle_t session, + ck_notification_t event, void *application); + +/* Forward reference. */ +struct ck_function_list; + +#define _CK_DECLARE_FUNCTION(name, args) \ +typedef ck_rv_t (*CK_ ## name) args; \ +ck_rv_t CK_SPEC name args + +_CK_DECLARE_FUNCTION (C_Initialize, (void *init_args)); +_CK_DECLARE_FUNCTION (C_Finalize, (void *reserved)); +_CK_DECLARE_FUNCTION (C_GetInfo, (struct ck_info *info)); +_CK_DECLARE_FUNCTION (C_GetFunctionList, + (struct ck_function_list **function_list)); + +_CK_DECLARE_FUNCTION (C_GetSlotList, + (unsigned char token_present, ck_slot_id_t *slot_list, + unsigned long *count)); +_CK_DECLARE_FUNCTION (C_GetSlotInfo, + (ck_slot_id_t slot_id, struct ck_slot_info *info)); +_CK_DECLARE_FUNCTION (C_GetTokenInfo, + (ck_slot_id_t slot_id, struct ck_token_info *info)); +_CK_DECLARE_FUNCTION (C_WaitForSlotEvent, + (ck_flags_t flags, ck_slot_id_t *slot, void *reserved)); +_CK_DECLARE_FUNCTION (C_GetMechanismList, + (ck_slot_id_t slot_id, + ck_mechanism_type_t *mechanism_list, + unsigned long *count)); +_CK_DECLARE_FUNCTION (C_GetMechanismInfo, + (ck_slot_id_t slot_id, ck_mechanism_type_t type, + struct ck_mechanism_info *info)); +_CK_DECLARE_FUNCTION (C_InitToken, + (ck_slot_id_t slot_id, unsigned char *pin, + unsigned long pin_len, unsigned char *label)); +_CK_DECLARE_FUNCTION (C_InitPIN, + (ck_session_handle_t session, unsigned char *pin, + unsigned long pin_len)); +_CK_DECLARE_FUNCTION (C_SetPIN, + (ck_session_handle_t session, unsigned char *old_pin, + unsigned long old_len, unsigned char *new_pin, + unsigned long new_len)); + +_CK_DECLARE_FUNCTION (C_OpenSession, + (ck_slot_id_t slot_id, ck_flags_t flags, + void *application, ck_notify_t notify, + ck_session_handle_t *session)); +_CK_DECLARE_FUNCTION (C_CloseSession, (ck_session_handle_t session)); +_CK_DECLARE_FUNCTION (C_CloseAllSessions, (ck_slot_id_t slot_id)); +_CK_DECLARE_FUNCTION (C_GetSessionInfo, + (ck_session_handle_t session, + struct ck_session_info *info)); +_CK_DECLARE_FUNCTION (C_GetOperationState, + (ck_session_handle_t session, + unsigned char *operation_state, + unsigned long *operation_state_len)); +_CK_DECLARE_FUNCTION (C_SetOperationState, + (ck_session_handle_t session, + unsigned char *operation_state, + unsigned long operation_state_len, + ck_object_handle_t encryption_key, + ck_object_handle_t authentiation_key)); +_CK_DECLARE_FUNCTION (C_Login, + (ck_session_handle_t session, ck_user_type_t user_type, + unsigned char *pin, unsigned long pin_len)); +_CK_DECLARE_FUNCTION (C_Logout, (ck_session_handle_t session)); + +_CK_DECLARE_FUNCTION (C_CreateObject, + (ck_session_handle_t session, + struct ck_attribute *templ, + unsigned long count, ck_object_handle_t *object)); +_CK_DECLARE_FUNCTION (C_CopyObject, + (ck_session_handle_t session, ck_object_handle_t object, + struct ck_attribute *templ, unsigned long count, + ck_object_handle_t *new_object)); +_CK_DECLARE_FUNCTION (C_DestroyObject, + (ck_session_handle_t session, + ck_object_handle_t object)); +_CK_DECLARE_FUNCTION (C_GetObjectSize, + (ck_session_handle_t session, + ck_object_handle_t object, + unsigned long *size)); +_CK_DECLARE_FUNCTION (C_GetAttributeValue, + (ck_session_handle_t session, + ck_object_handle_t object, + struct ck_attribute *templ, + unsigned long count)); +_CK_DECLARE_FUNCTION (C_SetAttributeValue, + (ck_session_handle_t session, + ck_object_handle_t object, + struct ck_attribute *templ, + unsigned long count)); +_CK_DECLARE_FUNCTION (C_FindObjectsInit, + (ck_session_handle_t session, + struct ck_attribute *templ, + unsigned long count)); +_CK_DECLARE_FUNCTION (C_FindObjects, + (ck_session_handle_t session, + ck_object_handle_t *object, + unsigned long max_object_count, + unsigned long *object_count)); +_CK_DECLARE_FUNCTION (C_FindObjectsFinal, + (ck_session_handle_t session)); + +_CK_DECLARE_FUNCTION (C_EncryptInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_Encrypt, + (ck_session_handle_t session, + unsigned char *data, unsigned long data_len, + unsigned char *encrypted_data, + unsigned long *encrypted_data_len)); +_CK_DECLARE_FUNCTION (C_EncryptUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len, + unsigned char *encrypted_part, + unsigned long *encrypted_part_len)); +_CK_DECLARE_FUNCTION (C_EncryptFinal, + (ck_session_handle_t session, + unsigned char *last_encrypted_part, + unsigned long *last_encrypted_part_len)); + +_CK_DECLARE_FUNCTION (C_DecryptInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_Decrypt, + (ck_session_handle_t session, + unsigned char *encrypted_data, + unsigned long encrypted_data_len, + unsigned char *data, unsigned long *data_len)); +_CK_DECLARE_FUNCTION (C_DecryptUpdate, + (ck_session_handle_t session, + unsigned char *encrypted_part, + unsigned long encrypted_part_len, + unsigned char *part, unsigned long *part_len)); +_CK_DECLARE_FUNCTION (C_DecryptFinal, + (ck_session_handle_t session, + unsigned char *last_part, + unsigned long *last_part_len)); + +_CK_DECLARE_FUNCTION (C_DigestInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism)); +_CK_DECLARE_FUNCTION (C_Digest, + (ck_session_handle_t session, + unsigned char *data, unsigned long data_len, + unsigned char *digest, + unsigned long *digest_len)); +_CK_DECLARE_FUNCTION (C_DigestUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len)); +_CK_DECLARE_FUNCTION (C_DigestKey, + (ck_session_handle_t session, ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_DigestFinal, + (ck_session_handle_t session, + unsigned char *digest, + unsigned long *digest_len)); + +_CK_DECLARE_FUNCTION (C_SignInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_Sign, + (ck_session_handle_t session, + unsigned char *data, unsigned long data_len, + unsigned char *signature, + unsigned long *signature_len)); +_CK_DECLARE_FUNCTION (C_SignUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len)); +_CK_DECLARE_FUNCTION (C_SignFinal, + (ck_session_handle_t session, + unsigned char *signature, + unsigned long *signature_len)); +_CK_DECLARE_FUNCTION (C_SignRecoverInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_SignRecover, + (ck_session_handle_t session, + unsigned char *data, unsigned long data_len, + unsigned char *signature, + unsigned long *signature_len)); + +_CK_DECLARE_FUNCTION (C_VerifyInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_Verify, + (ck_session_handle_t session, + unsigned char *data, unsigned long data_len, + unsigned char *signature, + unsigned long signature_len)); +_CK_DECLARE_FUNCTION (C_VerifyUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len)); +_CK_DECLARE_FUNCTION (C_VerifyFinal, + (ck_session_handle_t session, + unsigned char *signature, + unsigned long signature_len)); +_CK_DECLARE_FUNCTION (C_VerifyRecoverInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_VerifyRecover, + (ck_session_handle_t session, + unsigned char *signature, + unsigned long signature_len, + unsigned char *data, + unsigned long *data_len)); + +_CK_DECLARE_FUNCTION (C_DigestEncryptUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len, + unsigned char *encrypted_part, + unsigned long *encrypted_part_len)); +_CK_DECLARE_FUNCTION (C_DecryptDigestUpdate, + (ck_session_handle_t session, + unsigned char *encrypted_part, + unsigned long encrypted_part_len, + unsigned char *part, + unsigned long *part_len)); +_CK_DECLARE_FUNCTION (C_SignEncryptUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len, + unsigned char *encrypted_part, + unsigned long *encrypted_part_len)); +_CK_DECLARE_FUNCTION (C_DecryptVerifyUpdate, + (ck_session_handle_t session, + unsigned char *encrypted_part, + unsigned long encrypted_part_len, + unsigned char *part, + unsigned long *part_len)); + +_CK_DECLARE_FUNCTION (C_GenerateKey, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + struct ck_attribute *templ, + unsigned long count, + ck_object_handle_t *key)); +_CK_DECLARE_FUNCTION (C_GenerateKeyPair, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + struct ck_attribute *public_key_template, + unsigned long public_key_attribute_count, + struct ck_attribute *private_key_template, + unsigned long private_key_attribute_count, + ck_object_handle_t *public_key, + ck_object_handle_t *private_key)); +_CK_DECLARE_FUNCTION (C_WrapKey, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t wrapping_key, + ck_object_handle_t key, + unsigned char *wrapped_key, + unsigned long *wrapped_key_len)); +_CK_DECLARE_FUNCTION (C_UnwrapKey, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t unwrapping_key, + unsigned char *wrapped_key, + unsigned long wrapped_key_len, + struct ck_attribute *templ, + unsigned long attribute_count, + ck_object_handle_t *key)); +_CK_DECLARE_FUNCTION (C_DeriveKey, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t base_key, + struct ck_attribute *templ, + unsigned long attribute_count, + ck_object_handle_t *key)); + +_CK_DECLARE_FUNCTION (C_SeedRandom, + (ck_session_handle_t session, unsigned char *seed, + unsigned long seed_len)); +_CK_DECLARE_FUNCTION (C_GenerateRandom, + (ck_session_handle_t session, + unsigned char *random_data, + unsigned long random_len)); + +_CK_DECLARE_FUNCTION (C_GetFunctionStatus, (ck_session_handle_t session)); +_CK_DECLARE_FUNCTION (C_CancelFunction, (ck_session_handle_t session)); + + +struct ck_function_list +{ + struct ck_version version; + CK_C_Initialize C_Initialize; + CK_C_Finalize C_Finalize; + CK_C_GetInfo C_GetInfo; + CK_C_GetFunctionList C_GetFunctionList; + CK_C_GetSlotList C_GetSlotList; + CK_C_GetSlotInfo C_GetSlotInfo; + CK_C_GetTokenInfo C_GetTokenInfo; + CK_C_GetMechanismList C_GetMechanismList; + CK_C_GetMechanismInfo C_GetMechanismInfo; + CK_C_InitToken C_InitToken; + CK_C_InitPIN C_InitPIN; + CK_C_SetPIN C_SetPIN; + CK_C_OpenSession C_OpenSession; + CK_C_CloseSession C_CloseSession; + CK_C_CloseAllSessions C_CloseAllSessions; + CK_C_GetSessionInfo C_GetSessionInfo; + CK_C_GetOperationState C_GetOperationState; + CK_C_SetOperationState C_SetOperationState; + CK_C_Login C_Login; + CK_C_Logout C_Logout; + CK_C_CreateObject C_CreateObject; + CK_C_CopyObject C_CopyObject; + CK_C_DestroyObject C_DestroyObject; + CK_C_GetObjectSize C_GetObjectSize; + CK_C_GetAttributeValue C_GetAttributeValue; + CK_C_SetAttributeValue C_SetAttributeValue; + CK_C_FindObjectsInit C_FindObjectsInit; + CK_C_FindObjects C_FindObjects; + CK_C_FindObjectsFinal C_FindObjectsFinal; + CK_C_EncryptInit C_EncryptInit; + CK_C_Encrypt C_Encrypt; + CK_C_EncryptUpdate C_EncryptUpdate; + CK_C_EncryptFinal C_EncryptFinal; + CK_C_DecryptInit C_DecryptInit; + CK_C_Decrypt C_Decrypt; + CK_C_DecryptUpdate C_DecryptUpdate; + CK_C_DecryptFinal C_DecryptFinal; + CK_C_DigestInit C_DigestInit; + CK_C_Digest C_Digest; + CK_C_DigestUpdate C_DigestUpdate; + CK_C_DigestKey C_DigestKey; + CK_C_DigestFinal C_DigestFinal; + CK_C_SignInit C_SignInit; + CK_C_Sign C_Sign; + CK_C_SignUpdate C_SignUpdate; + CK_C_SignFinal C_SignFinal; + CK_C_SignRecoverInit C_SignRecoverInit; + CK_C_SignRecover C_SignRecover; + CK_C_VerifyInit C_VerifyInit; + CK_C_Verify C_Verify; + CK_C_VerifyUpdate C_VerifyUpdate; + CK_C_VerifyFinal C_VerifyFinal; + CK_C_VerifyRecoverInit C_VerifyRecoverInit; + CK_C_VerifyRecover C_VerifyRecover; + CK_C_DigestEncryptUpdate C_DigestEncryptUpdate; + CK_C_DecryptDigestUpdate C_DecryptDigestUpdate; + CK_C_SignEncryptUpdate C_SignEncryptUpdate; + CK_C_DecryptVerifyUpdate C_DecryptVerifyUpdate; + CK_C_GenerateKey C_GenerateKey; + CK_C_GenerateKeyPair C_GenerateKeyPair; + CK_C_WrapKey C_WrapKey; + CK_C_UnwrapKey C_UnwrapKey; + CK_C_DeriveKey C_DeriveKey; + CK_C_SeedRandom C_SeedRandom; + CK_C_GenerateRandom C_GenerateRandom; + CK_C_GetFunctionStatus C_GetFunctionStatus; + CK_C_CancelFunction C_CancelFunction; + CK_C_WaitForSlotEvent C_WaitForSlotEvent; +}; + + +typedef ck_rv_t (*ck_createmutex_t) (void **mutex); +typedef ck_rv_t (*ck_destroymutex_t) (void *mutex); +typedef ck_rv_t (*ck_lockmutex_t) (void *mutex); +typedef ck_rv_t (*ck_unlockmutex_t) (void *mutex); + + +struct ck_c_initialize_args +{ + ck_createmutex_t create_mutex; + ck_destroymutex_t destroy_mutex; + ck_lockmutex_t lock_mutex; + ck_unlockmutex_t unlock_mutex; + ck_flags_t flags; + void *reserved; +}; + + +#define CKF_LIBRARY_CANT_CREATE_OS_THREADS (1 << 0) +#define CKF_OS_LOCKING_OK (1 << 1) + +#define CKR_OK (0) +#define CKR_CANCEL (1) +#define CKR_HOST_MEMORY (2) +#define CKR_SLOT_ID_INVALID (3) +#define CKR_GENERAL_ERROR (5) +#define CKR_FUNCTION_FAILED (6) +#define CKR_ARGUMENTS_BAD (7) +#define CKR_NO_EVENT (8) +#define CKR_NEED_TO_CREATE_THREADS (9) +#define CKR_CANT_LOCK (0xa) +#define CKR_ATTRIBUTE_READ_ONLY (0x10) +#define CKR_ATTRIBUTE_SENSITIVE (0x11) +#define CKR_ATTRIBUTE_TYPE_INVALID (0x12) +#define CKR_ATTRIBUTE_VALUE_INVALID (0x13) +#define CKR_COPY_PROHIBITED (0x1A) +#define CKR_DATA_INVALID (0x20) +#define CKR_DATA_LEN_RANGE (0x21) +#define CKR_DEVICE_ERROR (0x30) +#define CKR_DEVICE_MEMORY (0x31) +#define CKR_DEVICE_REMOVED (0x32) +#define CKR_ENCRYPTED_DATA_INVALID (0x40) +#define CKR_ENCRYPTED_DATA_LEN_RANGE (0x41) +#define CKR_FUNCTION_CANCELED (0x50) +#define CKR_FUNCTION_NOT_PARALLEL (0x51) +#define CKR_FUNCTION_NOT_SUPPORTED (0x54) +#define CKR_KEY_HANDLE_INVALID (0x60) +#define CKR_KEY_SIZE_RANGE (0x62) +#define CKR_KEY_TYPE_INCONSISTENT (0x63) +#define CKR_KEY_NOT_NEEDED (0x64) +#define CKR_KEY_CHANGED (0x65) +#define CKR_KEY_NEEDED (0x66) +#define CKR_KEY_INDIGESTIBLE (0x67) +#define CKR_KEY_FUNCTION_NOT_PERMITTED (0x68) +#define CKR_KEY_NOT_WRAPPABLE (0x69) +#define CKR_KEY_UNEXTRACTABLE (0x6a) +#define CKR_MECHANISM_INVALID (0x70) +#define CKR_MECHANISM_PARAM_INVALID (0x71) +#define CKR_OBJECT_HANDLE_INVALID (0x82) +#define CKR_OPERATION_ACTIVE (0x90) +#define CKR_OPERATION_NOT_INITIALIZED (0x91) +#define CKR_PIN_INCORRECT (0xa0) +#define CKR_PIN_INVALID (0xa1) +#define CKR_PIN_LEN_RANGE (0xa2) +#define CKR_PIN_EXPIRED (0xa3) +#define CKR_PIN_LOCKED (0xa4) +#define CKR_SESSION_CLOSED (0xb0) +#define CKR_SESSION_COUNT (0xb1) +#define CKR_SESSION_HANDLE_INVALID (0xb3) +#define CKR_SESSION_PARALLEL_NOT_SUPPORTED (0xb4) +#define CKR_SESSION_READ_ONLY (0xb5) +#define CKR_SESSION_EXISTS (0xb6) +#define CKR_SESSION_READ_ONLY_EXISTS (0xb7) +#define CKR_SESSION_READ_WRITE_SO_EXISTS (0xb8) +#define CKR_SIGNATURE_INVALID (0xc0) +#define CKR_SIGNATURE_LEN_RANGE (0xc1) +#define CKR_TEMPLATE_INCOMPLETE (0xd0) +#define CKR_TEMPLATE_INCONSISTENT (0xd1) +#define CKR_TOKEN_NOT_PRESENT (0xe0) +#define CKR_TOKEN_NOT_RECOGNIZED (0xe1) +#define CKR_TOKEN_WRITE_PROTECTED (0xe2) +#define CKR_UNWRAPPING_KEY_HANDLE_INVALID (0xf0) +#define CKR_UNWRAPPING_KEY_SIZE_RANGE (0xf1) +#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT (0xf2) +#define CKR_USER_ALREADY_LOGGED_IN (0x100) +#define CKR_USER_NOT_LOGGED_IN (0x101) +#define CKR_USER_PIN_NOT_INITIALIZED (0x102) +#define CKR_USER_TYPE_INVALID (0x103) +#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN (0x104) +#define CKR_USER_TOO_MANY_TYPES (0x105) +#define CKR_WRAPPED_KEY_INVALID (0x110) +#define CKR_WRAPPED_KEY_LEN_RANGE (0x112) +#define CKR_WRAPPING_KEY_HANDLE_INVALID (0x113) +#define CKR_WRAPPING_KEY_SIZE_RANGE (0x114) +#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT (0x115) +#define CKR_RANDOM_SEED_NOT_SUPPORTED (0x120) +#define CKR_RANDOM_NO_RNG (0x121) +#define CKR_DOMAIN_PARAMS_INVALID (0x130) +#define CKR_BUFFER_TOO_SMALL (0x150) +#define CKR_SAVED_STATE_INVALID (0x160) +#define CKR_INFORMATION_SENSITIVE (0x170) +#define CKR_STATE_UNSAVEABLE (0x180) +#define CKR_CRYPTOKI_NOT_INITIALIZED (0x190) +#define CKR_CRYPTOKI_ALREADY_INITIALIZED (0x191) +#define CKR_MUTEX_BAD (0x1a0) +#define CKR_MUTEX_NOT_LOCKED (0x1a1) +#define CKR_NEW_PIN_MODE (0x1b0) +#define CKR_NEXT_OTP (0x1b1) +#define CKR_EXCEEDED_MAX_ITERATIONS (0x1b5) +#define CKR_FIPS_SELF_TEST_FAILED (0x1b6) +#define CKR_LIBRARY_LOAD_FAILED (0x1b7) +#define CKR_PIN_TOO_WEAK (0x1b8) +#define CKR_PUBLIC_KEY_INVALID (0x1b9) +#define CKR_FUNCTION_REJECTED (0x200) +#define CKR_VENDOR_DEFINED ((unsigned long) (1ul << 31)) + + + +/* Compatibility layer. */ + +#ifdef CRYPTOKI_COMPAT + +#undef CK_DEFINE_FUNCTION +#define CK_DEFINE_FUNCTION(retval, name) retval CK_SPEC name + +/* For NULL. */ +#include <stddef.h> + +typedef unsigned char CK_BYTE; +typedef unsigned char CK_CHAR; +typedef unsigned char CK_UTF8CHAR; +typedef unsigned char CK_BBOOL; +typedef unsigned long int CK_ULONG; +typedef long int CK_LONG; +typedef CK_BYTE *CK_BYTE_PTR; +typedef CK_CHAR *CK_CHAR_PTR; +typedef CK_UTF8CHAR *CK_UTF8CHAR_PTR; +typedef CK_ULONG *CK_ULONG_PTR; +typedef void *CK_VOID_PTR; +typedef void **CK_VOID_PTR_PTR; +#define CK_FALSE 0 +#define CK_TRUE 1 +#ifndef CK_DISABLE_TRUE_FALSE +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#endif + +typedef struct ck_version CK_VERSION; +typedef struct ck_version *CK_VERSION_PTR; + +typedef struct ck_info CK_INFO; +typedef struct ck_info *CK_INFO_PTR; + +typedef ck_slot_id_t *CK_SLOT_ID_PTR; + +typedef struct ck_slot_info CK_SLOT_INFO; +typedef struct ck_slot_info *CK_SLOT_INFO_PTR; + +typedef struct ck_token_info CK_TOKEN_INFO; +typedef struct ck_token_info *CK_TOKEN_INFO_PTR; + +typedef ck_session_handle_t *CK_SESSION_HANDLE_PTR; + +typedef struct ck_session_info CK_SESSION_INFO; +typedef struct ck_session_info *CK_SESSION_INFO_PTR; + +typedef ck_object_handle_t *CK_OBJECT_HANDLE_PTR; + +typedef ck_object_class_t *CK_OBJECT_CLASS_PTR; + +typedef struct ck_attribute CK_ATTRIBUTE; +typedef struct ck_attribute *CK_ATTRIBUTE_PTR; + +typedef struct ck_date CK_DATE; +typedef struct ck_date *CK_DATE_PTR; + +typedef ck_mechanism_type_t *CK_MECHANISM_TYPE_PTR; + +typedef struct ck_mechanism CK_MECHANISM; +typedef struct ck_mechanism *CK_MECHANISM_PTR; + +typedef struct ck_mechanism_info CK_MECHANISM_INFO; +typedef struct ck_mechanism_info *CK_MECHANISM_INFO_PTR; + +typedef struct ck_rsa_pkcs_oaep_params CK_RSA_PKCS_OAEP_PARAMS; +typedef struct ck_rsa_pkcs_oaep_params *CK_RSA_PKCS_OAEP_PARAMS_PTR; + +typedef struct ck_rsa_pkcs_pss_params CK_RSA_PKCS_PSS_PARAMS; +typedef struct ck_rsa_pkcs_pss_params *CK_RSA_PKCS_PSS_PARAMS_PTR; + +typedef struct ck_ecdh1_derive_params CK_ECDH1_DERIVE_PARAMS; +typedef struct ck_ecdh1_derive_params *CK_ECDH1_DERIVE_PARAMS_PTR; + +typedef struct ck_des_cbc_encrypt_data_params CK_DES_CBC_ENCRYPT_DATA_PARAMS; +typedef struct ck_des_cbc_encrypt_data_params *CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR; + +typedef struct ck_aes_cbc_encrypt_data_params CK_AES_CBC_ENCRYPT_DATA_PARAMS; +typedef struct ck_aes_cbc_encrypt_data_params *CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR; + +typedef struct ck_key_derivation_string_data CK_KEY_DERIVATION_STRING_DATA; +typedef struct ck_key_derivation_string_data *CK_KEY_DERIVATION_STRING_DATA_PTR; + +typedef struct ck_function_list CK_FUNCTION_LIST; +typedef struct ck_function_list *CK_FUNCTION_LIST_PTR; +typedef struct ck_function_list **CK_FUNCTION_LIST_PTR_PTR; + +typedef struct ck_c_initialize_args CK_C_INITIALIZE_ARGS; +typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR; + +#define NULL_PTR NULL + +/* Delete the helper macros defined at the top of the file. */ +#undef ck_flags_t +#undef ck_version + +#undef ck_info +#undef cryptoki_version +#undef manufacturer_id +#undef library_description +#undef library_version + +#undef ck_notification_t +#undef ck_slot_id_t + +#undef ck_slot_info +#undef slot_description +#undef hardware_version +#undef firmware_version + +#undef ck_token_info +#undef serial_number +#undef max_session_count +#undef session_count +#undef max_rw_session_count +#undef rw_session_count +#undef max_pin_len +#undef min_pin_len +#undef total_public_memory +#undef free_public_memory +#undef total_private_memory +#undef free_private_memory +#undef utc_time + +#undef ck_session_handle_t +#undef ck_user_type_t +#undef ck_state_t + +#undef ck_session_info +#undef slot_id +#undef device_error + +#undef ck_object_handle_t +#undef ck_object_class_t +#undef ck_hw_feature_type_t +#undef ck_key_type_t +#undef ck_certificate_type_t +#undef ck_attribute_type_t + +#undef ck_attribute +#undef value +#undef value_len + +#undef ck_date + +#undef ck_mechanism_type_t + +#undef ck_mechanism +#undef parameter +#undef parameter_len + +#undef ck_mechanism_info +#undef min_key_size +#undef max_key_size + +#undef ck_rsa_pkcs_oaep_params +#undef hash_alg +#undef source_data +#undef source_data_len +#undef slen + +#undef ck_ec_kdf_type_t +#undef shared_data_len +#undef shared_data +#undef public_data_len +#undef public_data +#undef private_data_len +#undef private_data +#undef public_data_len2 +#undef public_data2 +#undef public_key + +#undef ck_x9_42_dh_kdf_type_t +#undef other_info_len +#undef other_info + +#undef data +#undef len + +#undef ck_rv_t +#undef ck_notify_t + +#undef ck_function_list + +#undef ck_createmutex_t +#undef ck_destroymutex_t +#undef ck_lockmutex_t +#undef ck_unlockmutex_t + +#undef ck_c_initialize_args +#undef create_mutex +#undef destroy_mutex +#undef lock_mutex +#undef unlock_mutex +#undef reserved + +#endif /* CRYPTOKI_COMPAT */ + + +/* System dependencies. */ +#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32) +#pragma pack(pop, cryptoki) +#endif + +#if defined(__cplusplus) +} +#endif + +#endif /* PKCS11_H */ diff --git a/third_party/heimdal/lib/hx509/req.c b/third_party/heimdal/lib/hx509/req.c new file mode 100644 index 0000000..2b3f46d --- /dev/null +++ b/third_party/heimdal/lib/hx509/req.c @@ -0,0 +1,1520 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" +#include <pkcs10_asn1.h> + +typedef struct abitstring_s { + unsigned char *feats; + size_t feat_bytes; +} *abitstring; + +struct hx509_request_data { + hx509_context context; + hx509_name name; + SubjectPublicKeyInfo key; + KeyUsage ku; + ExtKeyUsage eku; + GeneralNames san; + struct abitstring_s authorized_EKUs; + struct abitstring_s authorized_SANs; + uint32_t nunsupported; /* Count of unsupported features requested */ + uint32_t nauthorized; /* Count of supported features authorized */ + uint32_t ku_are_authorized:1; +}; + +/** + * Allocate and initialize an hx509_request structure representing a PKCS#10 + * certificate signing request. + * + * @param context An hx509 context. + * @param req Where to put the new hx509_request object. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_init(hx509_context context, hx509_request *req) +{ + *req = calloc(1, sizeof(**req)); + if (*req == NULL) + return ENOMEM; + + (*req)->context = context; + return 0; +} + +/** + * Free a certificate signing request object. + * + * @param req A pointer to the hx509_request to free. + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_request_free(hx509_request *reqp) +{ + hx509_request req = *reqp; + + *reqp = NULL; + if (req == NULL) + return; + if (req->name) + hx509_name_free(&req->name); + free(req->authorized_EKUs.feats); + free(req->authorized_SANs.feats); + free_SubjectPublicKeyInfo(&req->key); + free_ExtKeyUsage(&req->eku); + free_GeneralNames(&req->san); + memset(req, 0, sizeof(*req)); + free(req); +} + +/** + * Set the subjectName of the CSR. + * + * @param context An hx509 context. + * @param req The hx509_request to alter. + * @param name The subjectName. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_set_name(hx509_context context, + hx509_request req, + hx509_name name) +{ + if (req->name) + hx509_name_free(&req->name); + if (name) { + int ret = hx509_name_copy(context, name, &req->name); + if (ret) + return ret; + } + return 0; +} + +/** + * Get the subject name requested by a CSR. + * + * @param context An hx509 context. + * @param req The hx509_request object. + * @param name Where to put the name. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_get_name(hx509_context context, + hx509_request req, + hx509_name *name) +{ + if (req->name == NULL) { + hx509_set_error_string(context, 0, EINVAL, "Request have no name"); + return EINVAL; + } + return hx509_name_copy(context, req->name, name); +} + +/** + * Set the subject public key requested by a CSR. + * + * @param context An hx509 context. + * @param req The hx509_request object. + * @param key The public key. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_set_SubjectPublicKeyInfo(hx509_context context, + hx509_request req, + const SubjectPublicKeyInfo *key) +{ + free_SubjectPublicKeyInfo(&req->key); + return copy_SubjectPublicKeyInfo(key, &req->key); +} + +/** + * Get the subject public key requested by a CSR. + * + * @param context An hx509 context. + * @param req The hx509_request object. + * @param key Where to put the key. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_get_SubjectPublicKeyInfo(hx509_context context, + hx509_request req, + SubjectPublicKeyInfo *key) +{ + return copy_SubjectPublicKeyInfo(&req->key, key); +} + +/** + * Set the key usage requested by a CSR. + * + * @param context An hx509 context. + * @param req The hx509_request object. + * @param ku The key usage. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_set_ku(hx509_context context, hx509_request req, KeyUsage ku) +{ + uint64_t n = KeyUsage2int(ku); + + if ((KeyUsage2int(req->ku) & n) != n) + req->ku_are_authorized = 0; + req->ku = ku; + return 0; +} + +/** + * Get the key usage requested by a CSR. + * + * @param context An hx509 context. + * @param req The hx509_request object. + * @param ku Where to put the key usage. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_get_ku(hx509_context context, hx509_request req, KeyUsage *ku) +{ + *ku = req->ku; + return 0; +} + +/** + * Add an extended key usage OID to a CSR. + * + * @param context An hx509 context. + * @param req The hx509_request object. + * @param oid The EKU OID. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_add_eku(hx509_context context, + hx509_request req, + const heim_oid *oid) +{ + void *val; + int ret; + + val = realloc(req->eku.val, sizeof(req->eku.val[0]) * (req->eku.len + 1)); + if (val == NULL) + return ENOMEM; + req->eku.val = val; + + ret = der_copy_oid(oid, &req->eku.val[req->eku.len]); + if (ret) + return ret; + + req->eku.len += 1; + + return 0; +} + +/** + * Add a GeneralName (Jabber ID) subject alternative name to a CSR. + * + * XXX Make this take a heim_octet_string, not a GeneralName*. + * + * @param context An hx509 context. + * @param req The hx509_request object. + * @param gn The GeneralName object. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_add_GeneralName(hx509_context context, + hx509_request req, + const GeneralName *gn) +{ + return add_GeneralNames(&req->san, gn); +} + +static int +add_utf8_other_san(hx509_context context, + GeneralNames *gns, + const heim_oid *oid, + const char *s) +{ + const PKIXXmppAddr us = (const PKIXXmppAddr)(uintptr_t)s; + GeneralName gn; + size_t size; + int ret; + + gn.element = choice_GeneralName_otherName; + gn.u.otherName.type_id.length = 0; + gn.u.otherName.type_id.components = 0; + gn.u.otherName.value.data = NULL; + gn.u.otherName.value.length = 0; + ret = der_copy_oid(oid, &gn.u.otherName.type_id); + if (ret == 0) + ASN1_MALLOC_ENCODE(PKIXXmppAddr, gn.u.otherName.value.data, + gn.u.otherName.value.length, &us, &size, ret); + if (ret == 0 && size != gn.u.otherName.value.length) + _hx509_abort("internal ASN.1 encoder error"); + if (ret == 0) + ret = add_GeneralNames(gns, &gn); + free_GeneralName(&gn); + if (ret) + hx509_set_error_string(context, 0, ret, "Out of memory"); + return ret; +} + +/** + * Add an xmppAddr (Jabber ID) subject alternative name to a CSR. + * + * @param context An hx509 context. + * @param req The hx509_request object. + * @param jid The XMPP address. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_add_xmpp_name(hx509_context context, + hx509_request req, + const char *jid) +{ + return add_utf8_other_san(context, &req->san, + &asn1_oid_id_pkix_on_xmppAddr, jid); +} + +/** + * Add a Microsoft UPN subject alternative name to a CSR. + * + * @param context An hx509 context. + * @param req The hx509_request object. + * @param hostname The XMPP address. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_add_ms_upn_name(hx509_context context, + hx509_request req, + const char *upn) +{ + return add_utf8_other_san(context, &req->san, &asn1_oid_id_pkinit_ms_san, + upn); +} + +/** + * Add a dNSName (hostname) subject alternative name to a CSR. + * + * @param context An hx509 context. + * @param req The hx509_request object. + * @param hostname The fully-qualified hostname. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_add_dns_name(hx509_context context, + hx509_request req, + const char *hostname) +{ + GeneralName name; + + memset(&name, 0, sizeof(name)); + name.element = choice_GeneralName_dNSName; + name.u.dNSName.data = rk_UNCONST(hostname); + name.u.dNSName.length = strlen(hostname); + + return add_GeneralNames(&req->san, &name); +} + +/** + * Add a dnsSRV (_service.hostname) subject alternative name to a CSR. + * + * @param context An hx509 context. + * @param req The hx509_request object. + * @param dnssrv The DNS SRV name. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_add_dns_srv(hx509_context context, + hx509_request req, + const char *dnssrv) +{ + GeneralName gn; + SRVName n; + size_t size; + int ret; + + memset(&n, 0, sizeof(n)); + memset(&gn, 0, sizeof(gn)); + gn.element = choice_GeneralName_otherName; + gn.u.otherName.type_id.length = 0; + gn.u.otherName.type_id.components = 0; + gn.u.otherName.value.data = NULL; + gn.u.otherName.value.length = 0; + n.length = strlen(dnssrv); + n.data = (void *)(uintptr_t)dnssrv; + ASN1_MALLOC_ENCODE(SRVName, + gn.u.otherName.value.data, + gn.u.otherName.value.length, &n, &size, ret); + if (ret == 0) + ret = der_copy_oid(&asn1_oid_id_pkix_on_dnsSRV, &gn.u.otherName.type_id); + if (ret == 0) + ret = add_GeneralNames(&req->san, &gn); + free_GeneralName(&gn); + return ret; +} + +/** + * Add an rfc822Name (e-mail address) subject alternative name to a CSR. + * + * @param context An hx509 context. + * @param req The hx509_request object. + * @param email The e-mail address. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_add_email(hx509_context context, + hx509_request req, + const char *email) +{ + GeneralName name; + + memset(&name, 0, sizeof(name)); + name.element = choice_GeneralName_rfc822Name; + name.u.rfc822Name.data = rk_UNCONST(email); + name.u.rfc822Name.length = strlen(email); + + return add_GeneralNames(&req->san, &name); +} + +/** + * Add a registeredID (OID) subject alternative name to a CSR. + * + * @param context An hx509 context. + * @param req The hx509_request object. + * @param oid The OID. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_add_registered(hx509_context context, + hx509_request req, + heim_oid *oid) +{ + GeneralName name; + int ret; + + memset(&name, 0, sizeof(name)); + name.element = choice_GeneralName_registeredID; + ret = der_copy_oid(oid, &name.u.registeredID); + if (ret) + return ret; + ret = add_GeneralNames(&req->san, &name); + free_GeneralName(&name); + return ret; +} + +/** + * Add a Kerberos V5 principal subject alternative name to a CSR. + * + * @param context An hx509 context. + * @param req The hx509_request object. + * @param princ The Kerberos principal name. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_add_pkinit(hx509_context context, + hx509_request req, + const char *princ) +{ + KRB5PrincipalName kn; + GeneralName gn; + int ret; + + memset(&kn, 0, sizeof(kn)); + memset(&gn, 0, sizeof(gn)); + gn.element = choice_GeneralName_otherName; + gn.u.otherName.type_id.length = 0; + gn.u.otherName.type_id.components = 0; + gn.u.otherName.value.data = NULL; + gn.u.otherName.value.length = 0; + ret = der_copy_oid(&asn1_oid_id_pkinit_san, &gn.u.otherName.type_id); + if (ret == 0) + ret = _hx509_make_pkinit_san(context, princ, &gn.u.otherName.value); + if (ret == 0) + ret = add_GeneralNames(&req->san, &gn); + free_GeneralName(&gn); + return ret; +} + +/* XXX Add DNSSRV and other SANs */ + +static int +get_exts(hx509_context context, + const hx509_request req, + Extensions *exts) +{ + size_t size; + int ret = 0; + + exts->val = NULL; + exts->len = 0; + + if (KeyUsage2int(req->ku)) { + Extension e; + + memset(&e, 0, sizeof(e)); + /* The critical field needs to be made DEFAULT FALSE... */ + e.critical = 1; + if (ret == 0) + ASN1_MALLOC_ENCODE(KeyUsage, e.extnValue.data, e.extnValue.length, + &req->ku, &size, ret); + if (ret == 0) + ret = der_copy_oid(&asn1_oid_id_x509_ce_keyUsage, &e.extnID); + if (ret == 0) + ret = add_Extensions(exts, &e); + free_Extension(&e); + } + if (ret == 0 && req->eku.len) { + Extension e; + + memset(&e, 0, sizeof(e)); + e.critical = 1; + if (ret == 0) + ASN1_MALLOC_ENCODE(ExtKeyUsage, + e.extnValue.data, e.extnValue.length, + &req->eku, &size, ret); + if (ret == 0) + ret = der_copy_oid(&asn1_oid_id_x509_ce_extKeyUsage, &e.extnID); + if (ret == 0) + ret = add_Extensions(exts, &e); + free_Extension(&e); + } + if (ret == 0 && req->san.len) { + Extension e; + + memset(&e, 0, sizeof(e)); + /* + * SANs are critical when the subject Name is empty. + * + * The empty DN check could probably stand to be a function we export. + */ + e.critical = FALSE; + if (req->name && + req->name->der_name.element == choice_Name_rdnSequence && + req->name->der_name.u.rdnSequence.len == 0) + e.critical = 1; + if (ret == 0) + ASN1_MALLOC_ENCODE(GeneralNames, + e.extnValue.data, e.extnValue.length, + &req->san, + &size, ret); + if (ret == 0) + ret = der_copy_oid(&asn1_oid_id_x509_ce_subjectAltName, &e.extnID); + if (ret == 0) + ret = add_Extensions(exts, &e); + free_Extension(&e); + } + + return ret; +} + +/** + * Get the KU/EKUs/SANs set on a request as a DER-encoding of Extensions. + * + * @param context An hx509 context. + * @param req The hx509_request object. + * @param exts_der Where to put the DER-encoded Extensions. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_get_exts(hx509_context context, + const hx509_request req, + heim_octet_string *exts_der) +{ + Extensions exts; + size_t size; + int ret; + + exts_der->data = NULL; + exts_der->length = 0; + ret = get_exts(context, req, &exts); + if (ret == 0 && exts.len /* Extensions has a min size constraint of 1 */) + ASN1_MALLOC_ENCODE(Extensions, exts_der->data, exts_der->length, + &exts, &size, ret); + free_Extensions(&exts); + return ret; +} + +/* XXX Add PEM */ + +/** + * Encode a CSR. + * + * @param context An hx509 context. + * @param req The hx509_request object. + * @param signer The private key corresponding to the CSR's subject public key. + * @param request Where to put the DER-encoded CSR. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_to_pkcs10(hx509_context context, + const hx509_request req, + const hx509_private_key signer, + heim_octet_string *request) +{ + CertificationRequest r; + Extensions exts; + heim_octet_string data; + size_t size; + int ret; + + request->data = NULL; + request->length = 0; + + data.length = 0; + data.data = NULL; + + if (req->name == NULL) { + hx509_set_error_string(context, 0, EINVAL, + "PKCS10 needs to have a subject"); + return EINVAL; + } + + memset(&r, 0, sizeof(r)); + + /* Setup CSR */ + r.certificationRequestInfo.version = pkcs10_v1; + ret = copy_Name(&req->name->der_name, + &r.certificationRequestInfo.subject); + if (ret == 0) + ret = copy_SubjectPublicKeyInfo(&req->key, + &r.certificationRequestInfo.subjectPKInfo); + + /* Encode extReq attribute with requested Certificate Extensions */ + + if (ret == 0) + ret = get_exts(context, req, &exts); + if (ret == 0 && exts.len) { + Attribute *a = NULL; /* Quiet VC */ + heim_any extns; + + r.certificationRequestInfo.attributes = + calloc(1, sizeof(r.certificationRequestInfo.attributes[0])); + if (r.certificationRequestInfo.attributes == NULL) + ret = ENOMEM; + if (ret == 0) { + r.certificationRequestInfo.attributes[0].len = 1; + r.certificationRequestInfo.attributes[0].val = + calloc(1, sizeof(r.certificationRequestInfo.attributes[0].val[0])); + if (r.certificationRequestInfo.attributes[0].val == NULL) + ret = ENOMEM; + if (ret == 0) + a = r.certificationRequestInfo.attributes[0].val; + } + if (ret == 0) + ASN1_MALLOC_ENCODE(Extensions, extns.data, extns.length, + &exts, &size, ret); + if (ret == 0 && a) + ret = der_copy_oid(&asn1_oid_id_pkcs9_extReq, &a->type); + if (ret == 0) + ret = add_AttributeValues(&a->value, &extns); + free_heim_any(&extns); + } + + /* Encode CSR body for signing */ + if (ret == 0) + ASN1_MALLOC_ENCODE(CertificationRequestInfo, data.data, data.length, + &r.certificationRequestInfo, &size, ret); + if (ret == 0 && data.length != size) + abort(); + + /* Self-sign CSR body */ + if (ret == 0) { + ret = _hx509_create_signature_bitstring(context, signer, + _hx509_crypto_default_sig_alg, + &data, + &r.signatureAlgorithm, + &r.signature); + } + free(data.data); + + /* Encode CSR */ + if (ret == 0) + ASN1_MALLOC_ENCODE(CertificationRequest, request->data, request->length, + &r, &size, ret); + if (ret == 0 && request->length != size) + abort(); + + free_CertificationRequest(&r); + free_Extensions(&exts); + return ret; +} + +/** + * Parse an encoded CSR and verify its self-signature. + * + * @param context An hx509 context. + * @param der The DER-encoded CSR. + * @param req Where to put request object. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_parse_der(hx509_context context, + heim_octet_string *der, + hx509_request *req) +{ + CertificationRequestInfo *rinfo = NULL; + CertificationRequest r; + hx509_cert signer = NULL; + Extensions exts; + size_t i, size; + int ret; + + memset(&exts, 0, sizeof(exts)); + + /* Initial setup and decoding of CSR */ + ret = hx509_request_init(context, req); + if (ret) + return ret; + ret = decode_CertificationRequest(der->data, der->length, &r, &size); + if (ret) { + hx509_set_error_string(context, 0, ret, "Failed to decode CSR"); + free(*req); + *req = NULL; + return ret; + } + rinfo = &r.certificationRequestInfo; + + /* + * Setup a 'signer' for verifying the self-signature for proof of + * possession. + * + * Sadly we need a "certificate" here because _hx509_verify_signature_*() + * functions want one as a signer even though all the verification + * functions that use the signer argument only ever use the spki of the + * signer certificate. + * + * FIXME Change struct signature_alg's verify_signature's prototype to use + * an spki instead of an hx509_cert as the signer! The we won't have + * to do this. + */ + if (ret == 0) { + Certificate c; + memset(&c, 0, sizeof(c)); + c.tbsCertificate.subjectPublicKeyInfo = rinfo->subjectPKInfo; + if ((signer = hx509_cert_init(context, &c, NULL)) == NULL) + ret = ENOMEM; + } + + /* Verify the signature */ + if (ret == 0) + ret = _hx509_verify_signature_bitstring(context, signer, + &r.signatureAlgorithm, + &rinfo->_save, + &r.signature); + if (ret) + hx509_set_error_string(context, 0, ret, + "CSR signature verification failed"); + hx509_cert_free(signer); + + /* Populate the hx509_request */ + if (ret == 0) + ret = hx509_request_set_SubjectPublicKeyInfo(context, *req, + &rinfo->subjectPKInfo); + if (ret == 0) + ret = _hx509_name_from_Name(&rinfo->subject, &(*req)->name); + + /* Extract KUs, EKUs, and SANs from the CSR's attributes */ + if (ret || !rinfo->attributes || !rinfo->attributes[0].len) + goto out; + + for (i = 0; ret == 0 && i < rinfo->attributes[0].len; i++) { + Attribute *a = &rinfo->attributes[0].val[i]; + heim_any *av = NULL; + + /* We only support Extensions request attributes */ + if (der_heim_oid_cmp(&a->type, &asn1_oid_id_pkcs9_extReq) != 0) { + char *oidstr = NULL; + + /* + * We need an HX509_TRACE facility for this sort of warning. + * + * We'd put the warning in the context and then allow the caller to + * extract and reset the warning. + * + * FIXME + */ + der_print_heim_oid(&a->type, '.', &oidstr); + warnx("Unknown or unsupported CSR attribute %s", + oidstr ? oidstr : "<error decoding OID>"); + free(oidstr); + continue; + } + if (!a->value.val) + continue; + + av = a->value.val; + ret = decode_Extensions(av->data, av->length, &exts, NULL); + if (ret) { + hx509_set_error_string(context, 0, ret, + "CSR signature verification failed " + "due to invalid extReq attribute"); + goto out; + } + } + for (i = 0; ret == 0 && i < exts.len; i++) { + const char *what = ""; + Extension *e = &exts.val[i]; + + if (der_heim_oid_cmp(&e->extnID, + &asn1_oid_id_x509_ce_keyUsage) == 0) { + ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, + &(*req)->ku, NULL); + what = "keyUsage"; + /* + * Count all KUs as one requested extension to be authorized, + * though the caller will have to check the KU values individually. + */ + if (KeyUsage2int((*req)->ku) & ~KeyUsage2int(int2KeyUsage(~0))) + (*req)->nunsupported++; + } else if (der_heim_oid_cmp(&e->extnID, + &asn1_oid_id_x509_ce_extKeyUsage) == 0) { + ret = decode_ExtKeyUsage(e->extnValue.data, e->extnValue.length, + &(*req)->eku, NULL); + what = "extKeyUsage"; + + /* + * Count each EKU as a separate requested extension to be + * authorized. + */ + } else if (der_heim_oid_cmp(&e->extnID, + &asn1_oid_id_x509_ce_subjectAltName) == 0) { + ret = decode_GeneralNames(e->extnValue.data, e->extnValue.length, + &(*req)->san, NULL); + what = "subjectAlternativeName"; + + /* + * Count each SAN as a separate requested extension to be + * authorized. + */ + } else { + char *oidstr = NULL; + + (*req)->nunsupported++; + + /* + * We need an HX509_TRACE facility for this sort of warning. + * + * We'd put the warning in the context and then allow the caller to + * extract and reset the warning. + * + * FIXME + */ + der_print_heim_oid(&e->extnID, '.', &oidstr); + warnx("Unknown or unsupported CSR extension request %s", + oidstr ? oidstr : "<error decoding OID>"); + free(oidstr); + } + if (ret) { + hx509_set_error_string(context, 0, ret, + "CSR signature verification failed " + "due to invalid %s extension", what); + break; + } + } + +out: + free_CertificationRequest(&r); + free_Extensions(&exts); + if (ret) + hx509_request_free(req); + return ret; +} + +/** + * Parse an encoded CSR and verify its self-signature. + * + * @param context An hx509 context. + * @param csr The name of a store containing the CSR ("PKCS10:/path/to/file") + * @param req Where to put request object. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_parse(hx509_context context, + const char *csr, + hx509_request *req) +{ + heim_octet_string d; + int ret; + + /* XXX Add support for PEM */ + if (strncmp(csr, "PKCS10:", 7) != 0) { + hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION, + "CSR location does not start with \"PKCS10:\": %s", + csr); + return HX509_UNSUPPORTED_OPERATION; + } + + ret = rk_undumpdata(csr + 7, &d.data, &d.length); + if (ret) { + hx509_set_error_string(context, 0, ret, "Could not read %s", csr); + return ret; + } + + ret = hx509_request_parse_der(context, &d, req); + free(d.data); + if (ret) + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + " (while parsing CSR from %s)", csr); + return ret; +} + +/** + * Get some EKU from a CSR. Usable as an iterator. + * + * @param context An hx509 context. + * @param req The hx509_request object. + * @param idx The index of the EKU (0 for the first) to return + * @param out A pointer to a char * variable where the OID will be placed + * (caller must free with free()) + * + * @return Zero on success, HX509_NO_ITEM if no such item exists (denoting + * iteration end), or an error. + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_get_eku(hx509_request req, + size_t idx, + char **out) +{ + *out = NULL; + if (idx >= req->eku.len) + return HX509_NO_ITEM; + return der_print_heim_oid(&req->eku.val[idx], '.', out); +} + +static int +abitstring_check(abitstring a, size_t n, int idx) +{ + size_t bytes; + + if (idx >= n) + return EINVAL; + + bytes = (idx + 1) / CHAR_BIT + (((idx + 1) % CHAR_BIT) ? 1 : 0); + if (a->feat_bytes < bytes) + return 0; + + return !!(a->feats[idx / CHAR_BIT] & (1UL<<(idx % CHAR_BIT))); +} + +/* + * Sets and returns 0 if not already set, -1 if already set. Positive return + * values are system errors. + */ +static int +abitstring_set(abitstring a, size_t n, int idx) +{ + size_t bytes; + + if (idx >= n) + return EINVAL; + + bytes = n / CHAR_BIT + ((n % CHAR_BIT) ? 1 : 0); + if (a->feat_bytes < bytes) { + unsigned char *tmp; + + if ((tmp = realloc(a->feats, bytes)) == NULL) + return ENOMEM; + memset(tmp + a->feat_bytes, 0, bytes - a->feat_bytes); + a->feats = tmp; + a->feat_bytes = bytes; + } + + if (!(a->feats[idx / CHAR_BIT] & (1UL<<(idx % CHAR_BIT)))) { + a->feats[idx / CHAR_BIT] |= 1UL<<(idx % CHAR_BIT); + return 0; + } + return -1; +} + +/* + * Resets and returns 0 if not already reset, -1 if already reset. Positive + * return values are system errors. + */ +static int +abitstring_reset(abitstring a, size_t n, int idx) +{ + size_t bytes; + + if (idx >= n) + return EINVAL; + + bytes = (idx + 1) / CHAR_BIT + (((idx + 1) % CHAR_BIT) ? 1 : 0); + if (a->feat_bytes >= bytes && + (a->feats[idx / CHAR_BIT] & (1UL<<(idx % CHAR_BIT)))) { + a->feats[idx / CHAR_BIT] &= ~(1UL<<(idx % CHAR_BIT)); + return 0; + } + return -1; +} + +static int +authorize_feat(hx509_request req, abitstring a, size_t n, int idx) +{ + int ret; + + ret = abitstring_set(a, n, idx); + switch (ret) { + case 0: + req->nauthorized++; + fallthrough; + case -1: + return 0; + default: + return ret; + } +} + +static int +reject_feat(hx509_request req, abitstring a, size_t n, int idx) +{ + int ret; + + ret = abitstring_reset(a, n, idx); + switch (ret) { + case 0: + req->nauthorized--; + fallthrough; + case -1: + return 0; + default: + return ret; + } +} + +/** + * Filter the requested KeyUsage and mark it authorized. + * + * @param req The hx509_request object. + * @param ku Permitted KeyUsage + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_request_authorize_ku(hx509_request req, KeyUsage ku) +{ + (void) hx509_request_set_ku(NULL, req, ku); + req->ku = int2KeyUsage(KeyUsage2int(req->ku) & KeyUsage2int(ku)); + if (KeyUsage2int(ku)) + req->ku_are_authorized = 1; +} + +/** + * Mark a requested EKU as authorized. + * + * @param req The hx509_request object. + * @param idx The index of an EKU that can be fetched with + * hx509_request_get_eku() + * + * @return Zero on success, an error otherwise. + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_authorize_eku(hx509_request req, size_t idx) +{ + return authorize_feat(req, &req->authorized_EKUs, req->eku.len, idx); +} + +/** + * Mark a requested EKU as not authorized. + * + * @param req The hx509_request object. + * @param idx The index of an EKU that can be fetched with + * hx509_request_get_eku() + * + * @return Zero on success, an error otherwise. + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_reject_eku(hx509_request req, size_t idx) +{ + return reject_feat(req, &req->authorized_EKUs, req->eku.len, idx); +} + +/** + * Check if an EKU has been marked authorized. + * + * @param req The hx509_request object. + * @param idx The index of an EKU that can be fetched with + * hx509_request_get_eku() + * + * @return Non-zero if authorized, zero if not. + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_eku_authorized_p(hx509_request req, size_t idx) +{ + return abitstring_check(&req->authorized_EKUs, req->eku.len, idx); +} + +/** + * Mark a requested SAN as authorized. + * + * @param req The hx509_request object. + * @param idx The cursor as modified by a SAN iterator. + * + * @return Zero on success, an error otherwise. + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_authorize_san(hx509_request req, size_t idx) +{ + return authorize_feat(req, &req->authorized_SANs, req->san.len, idx); +} + +/** + * Mark a requested SAN as not authorized. + * + * @param req The hx509_request object. + * @param idx The cursor as modified by a SAN iterator. + * + * @return Zero on success, an error otherwise. + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_reject_san(hx509_request req, size_t idx) +{ + return reject_feat(req, &req->authorized_SANs, req->san.len, idx); +} + +/** + * Check if a SAN has been marked authorized. + * + * @param req The hx509_request object. + * @param idx The index of a SAN that can be fetched with + * hx509_request_get_san() + * + * @return Non-zero if authorized, zero if not. + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_san_authorized_p(hx509_request req, size_t idx) +{ + return abitstring_check(&req->authorized_SANs, req->san.len, idx); +} + +/** + * Return the count of unsupported requested certificate extensions. + * + * @param req The hx509_request object. + * @return The number of unsupported certificate extensions requested. + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION size_t HX509_LIB_CALL +hx509_request_count_unsupported(hx509_request req) +{ + return req->nunsupported; +} + +/** + * Return the count of as-yet unauthorized certificate extensions requested. + * + * @param req The hx509_request object. + * @return The number of as-yet unauthorized certificate extensions requested. + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION size_t HX509_LIB_CALL +hx509_request_count_unauthorized(hx509_request req) +{ + size_t nrequested = req->eku.len + req->san.len + + (KeyUsage2int(req->ku) ? 1 : 0) + req->nunsupported; + + return nrequested - (req->nauthorized + req->ku_are_authorized); +} + +static hx509_san_type +san_map_type(GeneralName *san) +{ + static const struct { + const heim_oid *oid; + hx509_san_type type; + } map[] = { + { &asn1_oid_id_pkix_on_dnsSRV, HX509_SAN_TYPE_DNSSRV }, + { &asn1_oid_id_pkinit_san, HX509_SAN_TYPE_PKINIT }, + { &asn1_oid_id_pkix_on_xmppAddr, HX509_SAN_TYPE_XMPP }, + { &asn1_oid_id_pkinit_ms_san, HX509_SAN_TYPE_MS_UPN }, + { &asn1_oid_id_pkix_on_permanentIdentifier, HX509_SAN_TYPE_PERMANENT_ID }, + { &asn1_oid_id_on_hardwareModuleName, HX509_SAN_TYPE_HW_MODULE }, + }; + size_t i; + + switch (san->element) { + case choice_GeneralName_rfc822Name: return HX509_SAN_TYPE_EMAIL; + case choice_GeneralName_dNSName: return HX509_SAN_TYPE_DNSNAME; + case choice_GeneralName_directoryName: return HX509_SAN_TYPE_DN; + case choice_GeneralName_registeredID: return HX509_SAN_TYPE_REGISTERED_ID; + case choice_GeneralName_otherName: { + for (i = 0; i < sizeof(map)/sizeof(map[0]); i++) + if (der_heim_oid_cmp(&san->u.otherName.type_id, map[i].oid) == 0) + return map[i].type; + } + fallthrough; + default: return HX509_SAN_TYPE_UNSUPPORTED; + } +} + +/** + * Return the count of as-yet unauthorized certificate extensions requested. + * + * @param req The hx509_request object. + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION size_t HX509_LIB_CALL +hx509_request_get_san(hx509_request req, + size_t idx, + hx509_san_type *type, + char **out) +{ + struct rk_strpool *pool = NULL; + GeneralName *san; + + *out = NULL; + if (idx >= req->san.len) + return HX509_NO_ITEM; + + san = &req->san.val[idx]; + switch ((*type = san_map_type(san))) { + case HX509_SAN_TYPE_UNSUPPORTED: return 0; + case HX509_SAN_TYPE_EMAIL: + *out = strndup(san->u.rfc822Name.data, + san->u.rfc822Name.length); + break; + case HX509_SAN_TYPE_DNSNAME: + *out = strndup(san->u.dNSName.data, + san->u.dNSName.length); + break; + case HX509_SAN_TYPE_DNSSRV: { + SRVName name; + size_t size; + int ret; + + ret = decode_SRVName(san->u.otherName.value.data, + san->u.otherName.value.length, &name, &size); + if (ret) + return ret; + *out = strndup(name.data, name.length); + break; + } + case HX509_SAN_TYPE_PERMANENT_ID: { + PermanentIdentifier pi; + size_t size; + char *s = NULL; + int ret; + + ret = decode_PermanentIdentifier(san->u.otherName.value.data, + san->u.otherName.value.length, + &pi, &size); + if (ret == 0 && pi.assigner) { + ret = der_print_heim_oid(pi.assigner, '.', &s); + if (ret == 0 && + (pool = rk_strpoolprintf(NULL, "%s", s)) == NULL) + ret = ENOMEM; + } else if (ret == 0) { + pool = rk_strpoolprintf(NULL, "-"); + } + if (ret == 0 && + (pool = rk_strpoolprintf(pool, "%s%s", + *pi.identifierValue ? " " : "", + *pi.identifierValue ? *pi.identifierValue : "")) == NULL) + ret = ENOMEM; + if (ret == 0 && (*out = rk_strpoolcollect(pool)) == NULL) + ret = ENOMEM; + free_PermanentIdentifier(&pi); + free(s); + return ret; + } + case HX509_SAN_TYPE_HW_MODULE: { + HardwareModuleName hn; + size_t size; + char *s = NULL; + int ret; + + ret = decode_HardwareModuleName(san->u.otherName.value.data, + san->u.otherName.value.length, + &hn, &size); + if (ret == 0 && hn.hwSerialNum.length > 256) + hn.hwSerialNum.length = 256; + if (ret == 0) + ret = der_print_heim_oid(&hn.hwType, '.', &s); + if (ret == 0) + pool = rk_strpoolprintf(NULL, "%s", s); + if (ret == 0 && pool) + pool = rk_strpoolprintf(pool, " %.*s", + (int)hn.hwSerialNum.length, + (char *)hn.hwSerialNum.data); + if (ret == 0 && + (pool == NULL || (*out = rk_strpoolcollect(pool)) == NULL)) + ret = ENOMEM; + free_HardwareModuleName(&hn); + return ret; + } + case HX509_SAN_TYPE_DN: { + Name name; + + if (san->u.directoryName.element == choice_Name_rdnSequence) { + name.element = choice_Name_rdnSequence; + name.u.rdnSequence = san->u.directoryName.u.rdnSequence; + return _hx509_Name_to_string(&name, out); + } + *type = HX509_SAN_TYPE_UNSUPPORTED; + return 0; + } + case HX509_SAN_TYPE_REGISTERED_ID: + return der_print_heim_oid(&san->u.registeredID, '.', out); + case HX509_SAN_TYPE_XMPP: + fallthrough; + case HX509_SAN_TYPE_MS_UPN: { + int ret; + + ret = _hx509_unparse_utf8_string_name(req->context, &pool, + &san->u.otherName.value); + if ((*out = rk_strpoolcollect(pool)) == NULL) + return hx509_enomem(req->context); + return ret; + } + case HX509_SAN_TYPE_PKINIT: { + int ret; + + ret = _hx509_unparse_KRB5PrincipalName(req->context, &pool, + &san->u.otherName.value); + if ((*out = rk_strpoolcollect(pool)) == NULL) + return hx509_enomem(req->context); + return ret; + } + default: + *type = HX509_SAN_TYPE_UNSUPPORTED; + return 0; + } + if (*out == NULL) + return ENOMEM; + return 0; +} + +/** + * Display a CSR. + * + * @param context An hx509 context. + * @param req The hx509_request object. + * @param f A FILE * to print the CSR to. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_request + */ +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_request_print(hx509_context context, hx509_request req, FILE *f) +{ + uint64_t ku_num; + size_t i; + char *s = NULL; + int ret = 0; + + /* + * It's really unformatunate that we can't reuse more of the + * lib/hx509/print.c infrastructure here, as it's too focused on + * Certificates. + * + * For that matter, it's really annoying that CSRs don't more resemble + * Certificates. Indeed, an ideal CSR would look like this: + * + * CSRInfo ::= { + * desiredTbsCertificate TBSCertificate, + * attributes [1] SEQUENCE OF Attribute OPTIONAL, + * } + * CSR :: = { + * csrInfo CSRInfo, + * sigAlg AlgorithmIdentifier, + * signature BIT STRING + * } + * + * with everything related to the desired certificate in + * desiredTbsCertificate and anything not related to the CSR's contents in + * the 'attributes' field. + * + * That wouldn't allow one to have optional desired TBSCertificate + * features, but hey. One could express "gimme all or gimme nothing" as an + * attribute, or "gimme what you can", then check what one got. + */ + fprintf(f, "PKCS#10 CertificationRequest:\n"); + + if (req->name) { + char *subject; + ret = hx509_name_to_string(req->name, &subject); + if (ret) { + hx509_set_error_string(context, 0, ret, "Failed to print name"); + return ret; + } + fprintf(f, " name: %s\n", subject); + free(subject); + } + /* XXX Use hx509_request_get_ku() accessor */ + if ((ku_num = KeyUsage2int(req->ku))) { + const struct units *u; + const char *first = " "; + + fprintf(f, " key usage:"); + for (u = asn1_KeyUsage_units(); u->name; ++u) { + if ((ku_num & u->mult)) { + fprintf(f, "%s%s", first, u->name); + first = ", "; + ku_num &= ~u->mult; + } + } + if (ku_num) + fprintf(f, "%s<unknown-KeyUsage-value(s)>", first); + fprintf(f, "\n"); + } + if (req->eku.len) { + const char *first = " "; + + fprintf(f, " eku:"); + for (i = 0; ret == 0; i++) { + free(s); s = NULL; + ret = hx509_request_get_eku(req, i, &s); + if (ret) + break; + fprintf(f, "%s{%s}", first, s); + first = ", "; + } + fprintf(f, "\n"); + } + free(s); s = NULL; + if (ret == HX509_NO_ITEM) + ret = 0; + for (i = 0; ret == 0; i++) { + hx509_san_type san_type; + + free(s); s = NULL; + ret = hx509_request_get_san(req, i, &san_type, &s); + if (ret) + break; + switch (san_type) { + case HX509_SAN_TYPE_EMAIL: + fprintf(f, " san: rfc822Name: %s\n", s); + break; + case HX509_SAN_TYPE_DNSNAME: + fprintf(f, " san: dNSName: %s\n", s); + break; + case HX509_SAN_TYPE_DN: + fprintf(f, " san: dn: %s\n", s); + break; + case HX509_SAN_TYPE_REGISTERED_ID: + fprintf(f, " san: registeredID: %s\n", s); + break; + case HX509_SAN_TYPE_XMPP: + fprintf(f, " san: xmpp: %s\n", s); + break; + case HX509_SAN_TYPE_PKINIT: + fprintf(f, " san: pkinit: %s\n", s); + break; + case HX509_SAN_TYPE_MS_UPN: + fprintf(f, " san: ms-upn: %s\n", s); + break; + default: + fprintf(f, " san: <SAN type not supported>\n"); + break; + } + } + free(s); s = NULL; + if (ret == HX509_NO_ITEM) + ret = 0; + return ret; +} diff --git a/third_party/heimdal/lib/hx509/revoke.c b/third_party/heimdal/lib/hx509/revoke.c new file mode 100644 index 0000000..18b2f8f --- /dev/null +++ b/third_party/heimdal/lib/hx509/revoke.c @@ -0,0 +1,1650 @@ +/* + * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * @page page_revoke Revocation methods + * + * There are two revocation method for PKIX/X.509: CRL and OCSP. + * Revocation is needed if the private key is lost and + * stolen. Depending on how picky you are, you might want to make + * revocation for destroyed private keys too (smartcard broken), but + * that should not be a problem. + * + * CRL is a list of certificates that have expired. + * + * OCSP is an online checking method where the requestor sends a list + * of certificates to the OCSP server to return a signed reply if they + * are valid or not. Some services sends a OCSP reply as part of the + * hand-shake to make the revoktion decision simpler/faster for the + * client. + */ + +#include "hx_locl.h" + +struct revoke_crl { + char *path; + time_t last_modfied; + CRLCertificateList crl; + int verified; + int failed_verify; +}; + +struct revoke_ocsp { + char *path; + time_t last_modfied; + OCSPBasicOCSPResponse ocsp; + hx509_certs certs; + hx509_cert signer; +}; + + +struct hx509_revoke_ctx_data { + unsigned int ref; + struct { + struct revoke_crl *val; + size_t len; + } crls; + struct { + struct revoke_ocsp *val; + size_t len; + } ocsps; +}; + +/** + * Allocate a revokation context. Free with hx509_revoke_free(). + * + * @param context A hx509 context. + * @param ctx returns a newly allocated revokation context. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_revoke + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_revoke_init(hx509_context context, hx509_revoke_ctx *ctx) +{ + *ctx = calloc(1, sizeof(**ctx)); + if (*ctx == NULL) + return ENOMEM; + + (*ctx)->ref = 1; + (*ctx)->crls.len = 0; + (*ctx)->crls.val = NULL; + (*ctx)->ocsps.len = 0; + (*ctx)->ocsps.val = NULL; + + return 0; +} + +HX509_LIB_FUNCTION hx509_revoke_ctx HX509_LIB_CALL +_hx509_revoke_ref(hx509_revoke_ctx ctx) +{ + if (ctx == NULL) + return NULL; + if (ctx->ref == 0) + _hx509_abort("revoke ctx refcount == 0 on ref"); + ctx->ref++; + if (ctx->ref == UINT_MAX) + _hx509_abort("revoke ctx refcount == UINT_MAX on ref"); + return ctx; +} + +static void +free_ocsp(struct revoke_ocsp *ocsp) +{ + free(ocsp->path); + free_OCSPBasicOCSPResponse(&ocsp->ocsp); + hx509_certs_free(&ocsp->certs); + hx509_cert_free(ocsp->signer); +} + +/** + * Free a hx509 revokation context. + * + * @param ctx context to be freed + * + * @ingroup hx509_revoke + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_revoke_free(hx509_revoke_ctx *ctx) +{ + size_t i ; + + if (ctx == NULL || *ctx == NULL) + return; + + if ((*ctx)->ref == 0) + _hx509_abort("revoke ctx refcount == 0 on free"); + if (--(*ctx)->ref > 0) + return; + + for (i = 0; i < (*ctx)->crls.len; i++) { + free((*ctx)->crls.val[i].path); + free_CRLCertificateList(&(*ctx)->crls.val[i].crl); + } + + for (i = 0; i < (*ctx)->ocsps.len; i++) + free_ocsp(&(*ctx)->ocsps.val[i]); + free((*ctx)->ocsps.val); + + free((*ctx)->crls.val); + + memset(*ctx, 0, sizeof(**ctx)); + free(*ctx); + *ctx = NULL; +} + +static int +verify_ocsp(hx509_context context, + struct revoke_ocsp *ocsp, + time_t time_now, + hx509_certs certs, + hx509_cert parent) +{ + hx509_cert signer = NULL; + hx509_query q; + int ret; + + _hx509_query_clear(&q); + + /* + * Need to match on issuer too in case there are two CA that have + * issued the same name to a certificate. One example of this is + * the www.openvalidation.org test's ocsp validator. + */ + + q.match = HX509_QUERY_MATCH_ISSUER_NAME; + q.issuer_name = &_hx509_get_cert(parent)->tbsCertificate.issuer; + + switch(ocsp->ocsp.tbsResponseData.responderID.element) { + case choice_OCSPResponderID_byName: + q.match |= HX509_QUERY_MATCH_SUBJECT_NAME; + q.subject_name = &ocsp->ocsp.tbsResponseData.responderID.u.byName; + break; + case choice_OCSPResponderID_byKey: + q.match |= HX509_QUERY_MATCH_KEY_HASH_SHA1; + q.keyhash_sha1 = &ocsp->ocsp.tbsResponseData.responderID.u.byKey; + break; + } + + ret = hx509_certs_find(context, certs, &q, &signer); + if (ret && ocsp->certs) + ret = hx509_certs_find(context, ocsp->certs, &q, &signer); + if (ret == 0 && signer == NULL) + ret = HX509_CERT_NOT_FOUND; + if (ret) + goto out; + + /* + * If signer certificate isn't the CA certificate, lets check the + * it is the CA that signed the signer certificate and the OCSP EKU + * is set. + */ + if (hx509_cert_cmp(signer, parent) != 0) { + Certificate *p = _hx509_get_cert(parent); + Certificate *s = _hx509_get_cert(signer); + + ret = _hx509_cert_is_parent_cmp(s, p, 0); + if (ret != 0) { + ret = HX509_PARENT_NOT_CA; + hx509_set_error_string(context, 0, ret, "Revoke OCSP signer " + "doesn't have CA as signer certificate"); + goto out; + } + + ret = _hx509_verify_signature_bitstring(context, + parent, + &s->signatureAlgorithm, + &s->tbsCertificate._save, + &s->signatureValue); + if (ret) { + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + "OCSP signer signature invalid"); + goto out; + } + + ret = hx509_cert_check_eku(context, signer, + &asn1_oid_id_pkix_kp_OCSPSigning, 0); + if (ret) + goto out; + } + + ret = _hx509_verify_signature_bitstring(context, + signer, + &ocsp->ocsp.signatureAlgorithm, + &ocsp->ocsp.tbsResponseData._save, + &ocsp->ocsp.signature); + if (ret) { + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + "OCSP signature invalid"); + goto out; + } + + ocsp->signer = signer; + signer = NULL; +out: + if (signer) + hx509_cert_free(signer); + + return ret; +} + +/* + * + */ + +static int +parse_ocsp_basic(const void *data, size_t length, OCSPBasicOCSPResponse *basic) +{ + OCSPResponse resp; + size_t size; + int ret; + + memset(basic, 0, sizeof(*basic)); + + ret = decode_OCSPResponse(data, length, &resp, &size); + if (ret) + return ret; + if (length != size) { + free_OCSPResponse(&resp); + return ASN1_EXTRA_DATA; + } + + switch (resp.responseStatus) { + case successful: + break; + default: + free_OCSPResponse(&resp); + return HX509_REVOKE_WRONG_DATA; + } + + if (resp.responseBytes == NULL) { + free_OCSPResponse(&resp); + return EINVAL; + } + + ret = der_heim_oid_cmp(&resp.responseBytes->responseType, + &asn1_oid_id_pkix_ocsp_basic); + if (ret != 0) { + free_OCSPResponse(&resp); + return HX509_REVOKE_WRONG_DATA; + } + + ret = decode_OCSPBasicOCSPResponse(resp.responseBytes->response.data, + resp.responseBytes->response.length, + basic, + &size); + if (ret) { + free_OCSPResponse(&resp); + return ret; + } + if (size != resp.responseBytes->response.length) { + free_OCSPResponse(&resp); + free_OCSPBasicOCSPResponse(basic); + return ASN1_EXTRA_DATA; + } + free_OCSPResponse(&resp); + + return 0; +} + +/* + * + */ + +static int +load_ocsp(hx509_context context, struct revoke_ocsp *ocsp) +{ + OCSPBasicOCSPResponse basic; + hx509_certs certs = NULL; + size_t length; + struct stat sb; + void *data; + int ret; + + ret = rk_undumpdata(ocsp->path, &data, &length); + if (ret) + return ret; + + ret = stat(ocsp->path, &sb); + if (ret) { + rk_xfree(data); + return errno; + } + + ret = parse_ocsp_basic(data, length, &basic); + rk_xfree(data); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to parse OCSP response"); + return ret; + } + + if (basic.certs) { + size_t i; + + ret = hx509_certs_init(context, "MEMORY:ocsp-certs", 0, + NULL, &certs); + if (ret) { + free_OCSPBasicOCSPResponse(&basic); + return ret; + } + + for (i = 0; i < basic.certs->len; i++) { + hx509_cert c; + + c = hx509_cert_init(context, &basic.certs->val[i], NULL); + if (c == NULL) + continue; + + ret = hx509_certs_add(context, certs, c); + hx509_cert_free(c); + if (ret) + continue; + } + } + + ocsp->last_modfied = sb.st_mtime; + + free_OCSPBasicOCSPResponse(&ocsp->ocsp); + hx509_certs_free(&ocsp->certs); + hx509_cert_free(ocsp->signer); + + ocsp->ocsp = basic; + ocsp->certs = certs; + ocsp->signer = NULL; + + return 0; +} + +/** + * Add a OCSP file to the revokation context. + * + * @param context hx509 context + * @param ctx hx509 revokation context + * @param path path to file that is going to be added to the context. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_revoke + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_revoke_add_ocsp(hx509_context context, + hx509_revoke_ctx ctx, + const char *path) +{ + void *data; + int ret; + size_t i; + + if (strncmp(path, "FILE:", 5) != 0) { + hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION, + "unsupport type in %s", path); + return HX509_UNSUPPORTED_OPERATION; + } + + path += 5; + + for (i = 0; i < ctx->ocsps.len; i++) { + if (strcmp(ctx->ocsps.val[0].path, path) == 0) + return 0; + } + + data = realloc(ctx->ocsps.val, + (ctx->ocsps.len + 1) * sizeof(ctx->ocsps.val[0])); + if (data == NULL) { + hx509_clear_error_string(context); + return ENOMEM; + } + + ctx->ocsps.val = data; + + memset(&ctx->ocsps.val[ctx->ocsps.len], 0, + sizeof(ctx->ocsps.val[0])); + + ctx->ocsps.val[ctx->ocsps.len].path = strdup(path); + if (ctx->ocsps.val[ctx->ocsps.len].path == NULL) { + hx509_clear_error_string(context); + return ENOMEM; + } + + ret = load_ocsp(context, &ctx->ocsps.val[ctx->ocsps.len]); + if (ret) { + free(ctx->ocsps.val[ctx->ocsps.len].path); + return ret; + } + ctx->ocsps.len++; + + return ret; +} + +/* + * + */ + +static int +verify_crl(hx509_context context, + hx509_revoke_ctx ctx, + CRLCertificateList *crl, + time_t time_now, + hx509_certs certs, + hx509_cert parent) +{ + hx509_cert signer; + hx509_query q; + time_t t; + int ret; + + t = _hx509_Time2time_t(&crl->tbsCertList.thisUpdate); + if (t > time_now) { + hx509_set_error_string(context, 0, HX509_CRL_USED_BEFORE_TIME, + "CRL used before time"); + return HX509_CRL_USED_BEFORE_TIME; + } + + if (crl->tbsCertList.nextUpdate == NULL) { + hx509_set_error_string(context, 0, HX509_CRL_INVALID_FORMAT, + "CRL missing nextUpdate"); + return HX509_CRL_INVALID_FORMAT; + } + + t = _hx509_Time2time_t(crl->tbsCertList.nextUpdate); + if (t < time_now) { + hx509_set_error_string(context, 0, HX509_CRL_USED_AFTER_TIME, + "CRL used after time"); + return HX509_CRL_USED_AFTER_TIME; + } + + _hx509_query_clear(&q); + + /* + * If it's the signer have CRLSIGN bit set, use that as the signer + * cert for the certificate, otherwise, search for a certificate. + */ + if (_hx509_check_key_usage(context, parent, 1 << 6, FALSE) == 0) { + signer = hx509_cert_ref(parent); + } else { + q.match = HX509_QUERY_MATCH_SUBJECT_NAME; + q.match |= HX509_QUERY_KU_CRLSIGN; + q.subject_name = &crl->tbsCertList.issuer; + + ret = hx509_certs_find(context, certs, &q, &signer); + if (ret == 0 && signer == NULL) + ret = HX509_CERT_NOT_FOUND; + if (ret) { + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + "Failed to find certificate for CRL"); + return ret; + } + } + + ret = _hx509_verify_signature_bitstring(context, + signer, + &crl->signatureAlgorithm, + &crl->tbsCertList._save, + &crl->signatureValue); + if (ret) { + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + "CRL signature invalid"); + goto out; + } + + /* + * If signer is not CA cert, need to check revoke status of this + * CRL signing cert too, this include all parent CRL signer cert + * up to the root *sigh*, assume root at least hve CERTSIGN flag + * set. + */ + while (_hx509_check_key_usage(context, signer, 1 << 5, TRUE)) { + hx509_cert crl_parent; + + _hx509_query_clear(&q); + + q.match = HX509_QUERY_MATCH_SUBJECT_NAME; + q.match |= HX509_QUERY_KU_CRLSIGN; + q.subject_name = &_hx509_get_cert(signer)->tbsCertificate.issuer; + + ret = hx509_certs_find(context, certs, &q, &crl_parent); + if (ret) { + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + "Failed to find parent of CRL signer"); + goto out; + } + + ret = hx509_revoke_verify(context, + ctx, + certs, + time_now, + signer, + crl_parent); + hx509_cert_free(signer); + signer = crl_parent; + if (ret) { + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + "Failed to verify revocation " + "status of CRL signer"); + goto out; + } + } + +out: + hx509_cert_free(signer); + + return ret; +} + +static int +crl_parser(hx509_context context, const char *type, + const hx509_pem_header *header, + const void *data, size_t len, void *ctx) +{ + CRLCertificateList *crl = (CRLCertificateList *)ctx; + size_t size; + int ret; + + if (strcasecmp("X509 CRL", type) != 0) + return HX509_CRYPTO_SIG_INVALID_FORMAT; + + ret = decode_CRLCertificateList(data, len, crl, &size); + if (ret) + return ret; + + /* check signature is aligned */ + if (crl->signatureValue.length & 7) { + free_CRLCertificateList(crl); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + + return 0; +} + +static int +load_crl(hx509_context context, const char *path, time_t *t, CRLCertificateList *crl) +{ + struct stat sb; + size_t length; + void *data; + FILE *f; + int ret; + + memset(crl, 0, sizeof(*crl)); + + ret = stat(path, &sb); + if (ret) + return errno; + + *t = sb.st_mtime; + + if ((f = fopen(path, "r")) == NULL) + return errno; + + rk_cloexec_file(f); + + ret = hx509_pem_read(context, f, crl_parser, crl); + fclose(f); + + if (ret == HX509_PARSING_KEY_FAILED) { + + ret = rk_undumpdata(path, &data, &length); + if (ret) + return ret; + + ret = crl_parser(context, "X509 CRL", NULL, data, length, crl); + rk_xfree(data); + } + return ret; +} + +/** + * Add a CRL file to the revokation context. + * + * @param context hx509 context + * @param ctx hx509 revokation context + * @param path path to file that is going to be added to the context. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_revoke + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_revoke_add_crl(hx509_context context, + hx509_revoke_ctx ctx, + const char *path) +{ + void *data; + size_t i; + int ret; + + if (strncmp(path, "FILE:", 5) != 0) { + hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION, + "unsupported type in %s", path); + return HX509_UNSUPPORTED_OPERATION; + } + + + path += 5; + + for (i = 0; i < ctx->crls.len; i++) { + if (strcmp(ctx->crls.val[i].path, path) == 0) + return 0; + } + + data = realloc(ctx->crls.val, + (ctx->crls.len + 1) * sizeof(ctx->crls.val[0])); + if (data == NULL) { + hx509_clear_error_string(context); + return ENOMEM; + } + ctx->crls.val = data; + + memset(&ctx->crls.val[ctx->crls.len], 0, sizeof(ctx->crls.val[0])); + + ctx->crls.val[ctx->crls.len].path = strdup(path); + if (ctx->crls.val[ctx->crls.len].path == NULL) { + hx509_clear_error_string(context); + return ENOMEM; + } + + ret = load_crl(context, + path, + &ctx->crls.val[ctx->crls.len].last_modfied, + &ctx->crls.val[ctx->crls.len].crl); + if (ret) { + free(ctx->crls.val[ctx->crls.len].path); + return ret; + } + + ctx->crls.len++; + + return ret; +} + +/** + * Check that a certificate is not expired according to a revokation + * context. Also need the parent certificte to the check OCSP + * parent identifier. + * + * @param context hx509 context + * @param ctx hx509 revokation context + * @param certs + * @param now + * @param cert + * @param parent_cert + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_revoke + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_revoke_verify(hx509_context context, + hx509_revoke_ctx ctx, + hx509_certs certs, + time_t now, + hx509_cert cert, + hx509_cert parent_cert) +{ + const Certificate *c = _hx509_get_cert(cert); + const Certificate *p = _hx509_get_cert(parent_cert); + unsigned long i, j, k; + int ret; + + hx509_clear_error_string(context); + + for (i = 0; i < ctx->ocsps.len; i++) { + struct revoke_ocsp *ocsp = &ctx->ocsps.val[i]; + struct stat sb; + + /* check this ocsp apply to this cert */ + + /* check if there is a newer version of the file */ + ret = stat(ocsp->path, &sb); + if (ret == 0 && ocsp->last_modfied != sb.st_mtime) { + ret = load_ocsp(context, ocsp); + if (ret) + continue; + } + + /* verify signature in ocsp if not already done */ + if (ocsp->signer == NULL) { + ret = verify_ocsp(context, ocsp, now, certs, parent_cert); + if (ret) + continue; + } + + for (j = 0; j < ocsp->ocsp.tbsResponseData.responses.len; j++) { + heim_octet_string os; + + ret = der_heim_integer_cmp(&ocsp->ocsp.tbsResponseData.responses.val[j].certID.serialNumber, + &c->tbsCertificate.serialNumber); + if (ret != 0) + continue; + + /* verify issuer hashes hash */ + ret = _hx509_verify_signature(context, + NULL, + &ocsp->ocsp.tbsResponseData.responses.val[i].certID.hashAlgorithm, + &c->tbsCertificate.issuer._save, + &ocsp->ocsp.tbsResponseData.responses.val[i].certID.issuerNameHash); + if (ret != 0) + continue; + + os.data = p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data; + os.length = p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8; + + ret = _hx509_verify_signature(context, + NULL, + &ocsp->ocsp.tbsResponseData.responses.val[j].certID.hashAlgorithm, + &os, + &ocsp->ocsp.tbsResponseData.responses.val[j].certID.issuerKeyHash); + if (ret != 0) + continue; + + switch (ocsp->ocsp.tbsResponseData.responses.val[j].certStatus.element) { + case choice_OCSPCertStatus_good: + break; + case choice_OCSPCertStatus_revoked: + hx509_set_error_string(context, 0, + HX509_CERT_REVOKED, + "Certificate revoked by issuer in OCSP"); + return HX509_CERT_REVOKED; + case choice_OCSPCertStatus_unknown: + continue; + } + + /* don't allow the update to be in the future */ + if (ocsp->ocsp.tbsResponseData.responses.val[j].thisUpdate > + now + context->ocsp_time_diff) + continue; + + /* don't allow the next update to be in the past */ + if (ocsp->ocsp.tbsResponseData.responses.val[j].nextUpdate) { + if (*ocsp->ocsp.tbsResponseData.responses.val[j].nextUpdate < now) + continue; + } /* else should force a refetch, but can we ? */ + + return 0; + } + } + + for (i = 0; i < ctx->crls.len; i++) { + struct revoke_crl *crl = &ctx->crls.val[i]; + struct stat sb; + int diff; + + /* check if cert.issuer == crls.val[i].crl.issuer */ + ret = _hx509_name_cmp(&c->tbsCertificate.issuer, + &crl->crl.tbsCertList.issuer, &diff); + if (ret || diff) + continue; + + ret = stat(crl->path, &sb); + if (ret == 0 && crl->last_modfied != sb.st_mtime) { + CRLCertificateList cl; + + ret = load_crl(context, crl->path, &crl->last_modfied, &cl); + if (ret == 0) { + free_CRLCertificateList(&crl->crl); + crl->crl = cl; + crl->verified = 0; + crl->failed_verify = 0; + } + } + if (crl->failed_verify) + continue; + + /* verify signature in crl if not already done */ + if (crl->verified == 0) { + ret = verify_crl(context, ctx, &crl->crl, now, certs, parent_cert); + if (ret) { + crl->failed_verify = 1; + continue; + } + crl->verified = 1; + } + + if (crl->crl.tbsCertList.crlExtensions) { + for (j = 0; j < crl->crl.tbsCertList.crlExtensions->len; j++) { + if (crl->crl.tbsCertList.crlExtensions->val[j].critical) { + hx509_set_error_string(context, 0, + HX509_CRL_UNKNOWN_EXTENSION, + "Unknown CRL extension"); + return HX509_CRL_UNKNOWN_EXTENSION; + } + } + } + + if (crl->crl.tbsCertList.revokedCertificates == NULL) + return 0; + + /* check if cert is in crl */ + for (j = 0; j < crl->crl.tbsCertList.revokedCertificates->len; j++) { + time_t t; + + ret = der_heim_integer_cmp(&crl->crl.tbsCertList.revokedCertificates->val[j].userCertificate, + &c->tbsCertificate.serialNumber); + if (ret != 0) + continue; + + t = _hx509_Time2time_t(&crl->crl.tbsCertList.revokedCertificates->val[j].revocationDate); + if (t > now) + continue; + + if (crl->crl.tbsCertList.revokedCertificates->val[j].crlEntryExtensions) + for (k = 0; k < crl->crl.tbsCertList.revokedCertificates->val[j].crlEntryExtensions->len; k++) + if (crl->crl.tbsCertList.revokedCertificates->val[j].crlEntryExtensions->val[k].critical) + return HX509_CRL_UNKNOWN_EXTENSION; + + hx509_set_error_string(context, 0, + HX509_CERT_REVOKED, + "Certificate revoked by issuer in CRL"); + return HX509_CERT_REVOKED; + } + + return 0; + } + + + if (context->flags & HX509_CTX_VERIFY_MISSING_OK) + return 0; + hx509_set_error_string(context, HX509_ERROR_APPEND, + HX509_REVOKE_STATUS_MISSING, + "No revocation status found for certificates"); + return HX509_REVOKE_STATUS_MISSING; +} + +struct ocsp_add_ctx { + OCSPTBSRequest *req; + hx509_certs certs; + const AlgorithmIdentifier *digest; + hx509_cert parent; +}; + +static int HX509_LIB_CALL +add_to_req(hx509_context context, void *ptr, hx509_cert cert) +{ + struct ocsp_add_ctx *ctx = ptr; + OCSPInnerRequest *one; + hx509_cert parent = NULL; + Certificate *p, *c = _hx509_get_cert(cert); + heim_octet_string os; + int ret; + hx509_query q; + void *d; + + d = realloc(ctx->req->requestList.val, + sizeof(ctx->req->requestList.val[0]) * + (ctx->req->requestList.len + 1)); + if (d == NULL) + return ENOMEM; + ctx->req->requestList.val = d; + + one = &ctx->req->requestList.val[ctx->req->requestList.len]; + memset(one, 0, sizeof(*one)); + + _hx509_query_clear(&q); + + q.match |= HX509_QUERY_FIND_ISSUER_CERT; + q.subject = c; + + ret = hx509_certs_find(context, ctx->certs, &q, &parent); + if (ret) + goto out; + + if (ctx->parent) { + if (hx509_cert_cmp(ctx->parent, parent) != 0) { + ret = HX509_REVOKE_NOT_SAME_PARENT; + hx509_set_error_string(context, 0, ret, + "Not same parent certifate as " + "last certificate in request"); + goto out; + } + } else + ctx->parent = hx509_cert_ref(parent); + + p = _hx509_get_cert(parent); + + ret = copy_AlgorithmIdentifier(ctx->digest, &one->reqCert.hashAlgorithm); + if (ret) + goto out; + + ret = _hx509_create_signature(context, + NULL, + &one->reqCert.hashAlgorithm, + &c->tbsCertificate.issuer._save, + NULL, + &one->reqCert.issuerNameHash); + if (ret) + goto out; + + os.data = p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data; + os.length = + p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8; + + ret = _hx509_create_signature(context, + NULL, + &one->reqCert.hashAlgorithm, + &os, + NULL, + &one->reqCert.issuerKeyHash); + if (ret) + goto out; + + ret = copy_CertificateSerialNumber(&c->tbsCertificate.serialNumber, + &one->reqCert.serialNumber); + if (ret) + goto out; + + ctx->req->requestList.len++; +out: + hx509_cert_free(parent); + if (ret) { + free_OCSPInnerRequest(one); + memset(one, 0, sizeof(*one)); + } + + return ret; +} + +/** + * Create an OCSP request for a set of certificates. + * + * @param context a hx509 context + * @param reqcerts list of certificates to request ocsp data for + * @param pool certificate pool to use when signing + * @param signer certificate to use to sign the request + * @param digest the signing algorithm in the request, if NULL use the + * default signature algorithm, + * @param request the encoded request, free with free_heim_octet_string(). + * @param nonce nonce in the request, free with free_heim_octet_string(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_revoke + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ocsp_request(hx509_context context, + hx509_certs reqcerts, + hx509_certs pool, + hx509_cert signer, + const AlgorithmIdentifier *digest, + heim_octet_string *request, + heim_octet_string *nonce) +{ + OCSPRequest req; + size_t size; + int ret; + struct ocsp_add_ctx ctx; + Extensions *es; + + memset(&req, 0, sizeof(req)); + + if (digest == NULL) + digest = _hx509_crypto_default_digest_alg; + + ctx.req = &req.tbsRequest; + ctx.certs = pool; + ctx.digest = digest; + ctx.parent = NULL; + + ret = hx509_certs_iter_f(context, reqcerts, add_to_req, &ctx); + hx509_cert_free(ctx.parent); + if (ret) + goto out; + + if (nonce) { + req.tbsRequest.requestExtensions = + calloc(1, sizeof(*req.tbsRequest.requestExtensions)); + if (req.tbsRequest.requestExtensions == NULL) { + ret = ENOMEM; + goto out; + } + + es = req.tbsRequest.requestExtensions; + + es->val = calloc(es->len, sizeof(es->val[0])); + if (es->val == NULL) { + ret = ENOMEM; + goto out; + } + es->len = 1; + ret = der_copy_oid(&asn1_oid_id_pkix_ocsp_nonce, &es->val[0].extnID); + if (ret) { + free_OCSPRequest(&req); + return ret; + } + + es->val[0].extnValue.data = malloc(10); + if (es->val[0].extnValue.data == NULL) { + ret = ENOMEM; + goto out; + } + es->val[0].extnValue.length = 10; + + ret = RAND_bytes(es->val[0].extnValue.data, + es->val[0].extnValue.length); + if (ret != 1) { + ret = HX509_CRYPTO_INTERNAL_ERROR; + goto out; + } + ret = der_copy_octet_string(nonce, &es->val[0].extnValue); + if (ret) { + ret = ENOMEM; + goto out; + } + } + + ASN1_MALLOC_ENCODE(OCSPRequest, request->data, request->length, + &req, &size, ret); + free_OCSPRequest(&req); + if (ret) + goto out; + if (size != request->length) + _hx509_abort("internal ASN.1 encoder error"); + + return 0; + +out: + free_OCSPRequest(&req); + return ret; +} + +static char * +printable_time(time_t t) +{ + static char s[128]; + char *p; + if ((p = ctime(&t)) == NULL) + strlcpy(s, "?", sizeof(s)); + else { + strlcpy(s, p + 4, sizeof(s)); + s[20] = 0; + } + return s; +} + +/* + * + */ + +static int +print_ocsp(hx509_context context, struct revoke_ocsp *ocsp, FILE *out) +{ + int ret = 0; + size_t i; + + fprintf(out, "signer: "); + + switch(ocsp->ocsp.tbsResponseData.responderID.element) { + case choice_OCSPResponderID_byName: { + hx509_name n; + char *s; + _hx509_name_from_Name(&ocsp->ocsp.tbsResponseData.responderID.u.byName, &n); + hx509_name_to_string(n, &s); + hx509_name_free(&n); + fprintf(out, " byName: %s\n", s); + free(s); + break; + } + case choice_OCSPResponderID_byKey: { + char *s; + hex_encode(ocsp->ocsp.tbsResponseData.responderID.u.byKey.data, + ocsp->ocsp.tbsResponseData.responderID.u.byKey.length, + &s); + fprintf(out, " byKey: %s\n", s); + free(s); + break; + } + default: + _hx509_abort("choice_OCSPResponderID unknown"); + break; + } + + fprintf(out, "producedAt: %s\n", + printable_time(ocsp->ocsp.tbsResponseData.producedAt)); + + fprintf(out, "replies: %d\n", ocsp->ocsp.tbsResponseData.responses.len); + + for (i = 0; i < ocsp->ocsp.tbsResponseData.responses.len; i++) { + const char *status; + switch (ocsp->ocsp.tbsResponseData.responses.val[i].certStatus.element) { + case choice_OCSPCertStatus_good: + status = "good"; + break; + case choice_OCSPCertStatus_revoked: + status = "revoked"; + break; + case choice_OCSPCertStatus_unknown: + status = "unknown"; + break; + default: + status = "element unknown"; + } + + fprintf(out, "\t%llu. status: %s\n", (unsigned long long)i, status); + + fprintf(out, "\tthisUpdate: %s\n", + printable_time(ocsp->ocsp.tbsResponseData.responses.val[i].thisUpdate)); + if (ocsp->ocsp.tbsResponseData.responses.val[i].nextUpdate) + fprintf(out, "\tproducedAt: %s\n", + printable_time(ocsp->ocsp.tbsResponseData.responses.val[i].thisUpdate)); + + } + + fprintf(out, "appended certs:\n"); + if (ocsp->certs) + ret = hx509_certs_iter_f(context, ocsp->certs, hx509_ci_print_names, out); + + return ret; +} + +static int +print_crl(hx509_context context, struct revoke_crl *crl, FILE *out) +{ + { + hx509_name n; + char *s; + _hx509_name_from_Name(&crl->crl.tbsCertList.issuer, &n); + hx509_name_to_string(n, &s); + hx509_name_free(&n); + fprintf(out, " issuer: %s\n", s); + free(s); + } + + fprintf(out, " thisUpdate: %s\n", + printable_time(_hx509_Time2time_t(&crl->crl.tbsCertList.thisUpdate))); + + return 0; +} + + +/* + * + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_revoke_print(hx509_context context, + hx509_revoke_ctx ctx, + FILE *out) +{ + int saved_ret = 0, ret; + size_t n; + + for (n = 0; n < ctx->ocsps.len; n++) { + struct revoke_ocsp *ocsp = &ctx->ocsps.val[n]; + + fprintf(out, "OCSP %s\n", ocsp->path); + + ret = print_ocsp(context, ocsp, out); + if (ret) { + fprintf(out, "failure printing OCSP: %d\n", ret); + saved_ret = ret; + } + } + + for (n = 0; n < ctx->crls.len; n++) { + struct revoke_crl *crl = &ctx->crls.val[n]; + + fprintf(out, "CRL %s\n", crl->path); + + ret = print_crl(context, crl, out); + if (ret) { + fprintf(out, "failure printing CRL: %d\n", ret); + saved_ret = ret; + } + } + return saved_ret; + +} + +/** + * Print the OCSP reply stored in a file. + * + * @param context a hx509 context + * @param path path to a file with a OCSP reply + * @param out the out FILE descriptor to print the reply on + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_revoke + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_revoke_ocsp_print(hx509_context context, const char *path, FILE *out) +{ + struct revoke_ocsp ocsp; + int ret; + + if (out == NULL) + out = stdout; + + memset(&ocsp, 0, sizeof(ocsp)); + + ocsp.path = strdup(path); + if (ocsp.path == NULL) + return ENOMEM; + + ret = load_ocsp(context, &ocsp); + if (ret) { + free_ocsp(&ocsp); + return ret; + } + + ret = print_ocsp(context, &ocsp, out); + + free_ocsp(&ocsp); + return ret; +} + +/** + * Verify that the certificate is part of the OCSP reply and it's not + * expired. Doesn't verify signature the OCSP reply or it's done by a + * authorized sender, that is assumed to be already done. + * + * @param context a hx509 context + * @param now the time right now, if 0, use the current time. + * @param cert the certificate to verify + * @param flags flags control the behavior + * @param data pointer to the encode ocsp reply + * @param length the length of the encode ocsp reply + * @param expiration return the time the OCSP will expire and need to + * be rechecked. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_verify + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ocsp_verify(hx509_context context, + time_t now, + hx509_cert cert, + int flags, + const void *data, size_t length, + time_t *expiration) +{ + const Certificate *c = _hx509_get_cert(cert); + OCSPBasicOCSPResponse basic; + int ret; + size_t i; + + if (now == 0) + now = time(NULL); + + *expiration = 0; + + ret = parse_ocsp_basic(data, length, &basic); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to parse OCSP response"); + return ret; + } + + for (i = 0; i < basic.tbsResponseData.responses.len; i++) { + + ret = der_heim_integer_cmp(&basic.tbsResponseData.responses.val[i].certID.serialNumber, + &c->tbsCertificate.serialNumber); + if (ret != 0) + continue; + + /* verify issuer hashes hash */ + ret = _hx509_verify_signature(context, + NULL, + &basic.tbsResponseData.responses.val[i].certID.hashAlgorithm, + &c->tbsCertificate.issuer._save, + &basic.tbsResponseData.responses.val[i].certID.issuerNameHash); + if (ret != 0) + continue; + + switch (basic.tbsResponseData.responses.val[i].certStatus.element) { + case choice_OCSPCertStatus_good: + break; + case choice_OCSPCertStatus_revoked: + case choice_OCSPCertStatus_unknown: + continue; + } + + /* don't allow the update to be in the future */ + if (basic.tbsResponseData.responses.val[i].thisUpdate > + now + context->ocsp_time_diff) + continue; + + /* don't allow the next update to be in the past */ + if (basic.tbsResponseData.responses.val[i].nextUpdate) { + if (*basic.tbsResponseData.responses.val[i].nextUpdate < now) + continue; + *expiration = *basic.tbsResponseData.responses.val[i].nextUpdate; + } else + *expiration = now; + + free_OCSPBasicOCSPResponse(&basic); + return 0; + } + + free_OCSPBasicOCSPResponse(&basic); + + { + hx509_name name; + char *subject; + + ret = hx509_cert_get_subject(cert, &name); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + ret = hx509_name_to_string(name, &subject); + hx509_name_free(&name); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + hx509_set_error_string(context, 0, HX509_CERT_NOT_IN_OCSP, + "Certificate %s not in OCSP response " + "or not good", + subject); + free(subject); + } +out: + return HX509_CERT_NOT_IN_OCSP; +} + +struct hx509_crl { + hx509_certs revoked; + time_t expire; +}; + +/** + * Create a CRL context. Use hx509_crl_free() to free the CRL context. + * + * @param context a hx509 context. + * @param crl return pointer to a newly allocated CRL context. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_verify + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_crl_alloc(hx509_context context, hx509_crl *crl) +{ + int ret; + + *crl = calloc(1, sizeof(**crl)); + if (*crl == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + + ret = hx509_certs_init(context, "MEMORY:crl", 0, NULL, &(*crl)->revoked); + if (ret) { + free(*crl); + *crl = NULL; + return ret; + } + (*crl)->expire = 0; + return ret; +} + +/** + * Add revoked certificate to an CRL context. + * + * @param context a hx509 context. + * @param crl the CRL to add the revoked certificate to. + * @param certs keyset of certificate to revoke. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_verify + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_crl_add_revoked_certs(hx509_context context, + hx509_crl crl, + hx509_certs certs) +{ + return hx509_certs_merge(context, crl->revoked, certs); +} + +/** + * Set the lifetime of a CRL context. + * + * @param context a hx509 context. + * @param crl a CRL context + * @param delta delta time the certificate is valid, library adds the + * current time to this. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_verify + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_crl_lifetime(hx509_context context, hx509_crl crl, int delta) +{ + crl->expire = time(NULL) + delta; + return 0; +} + +/** + * Free a CRL context. + * + * @param context a hx509 context. + * @param crl a CRL context to free. + * + * @ingroup hx509_verify + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +hx509_crl_free(hx509_context context, hx509_crl *crl) +{ + if (*crl == NULL) + return; + hx509_certs_free(&(*crl)->revoked); + memset(*crl, 0, sizeof(**crl)); + free(*crl); + *crl = NULL; +} + +static int HX509_LIB_CALL +add_revoked(hx509_context context, void *ctx, hx509_cert cert) +{ + TBSCRLCertList *c = ctx; + unsigned int num; + void *ptr; + int ret; + + num = c->revokedCertificates->len; + ptr = realloc(c->revokedCertificates->val, + (num + 1) * sizeof(c->revokedCertificates->val[0])); + if (ptr == NULL) { + hx509_clear_error_string(context); + return ENOMEM; + } + c->revokedCertificates->val = ptr; + + ret = hx509_cert_get_serialnumber(cert, + &c->revokedCertificates->val[num].userCertificate); + if (ret) { + hx509_clear_error_string(context); + return ret; + } + c->revokedCertificates->val[num].revocationDate.element = + choice_Time_generalTime; + c->revokedCertificates->val[num].revocationDate.u.generalTime = + time(NULL) - 3600 * 24; + c->revokedCertificates->val[num].crlEntryExtensions = NULL; + + c->revokedCertificates->len++; + + return 0; +} + +/** + * Sign a CRL and return an encode certificate. + * + * @param context a hx509 context. + * @param signer certificate to sign the CRL with + * @param crl the CRL to sign + * @param os return the signed and encoded CRL, free with + * free_heim_octet_string() + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_verify + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_crl_sign(hx509_context context, + hx509_cert signer, + hx509_crl crl, + heim_octet_string *os) +{ + const AlgorithmIdentifier *sigalg = _hx509_crypto_default_sig_alg; + CRLCertificateList c; + size_t size; + int ret; + hx509_private_key signerkey; + + memset(&c, 0, sizeof(c)); + + signerkey = _hx509_cert_private_key(signer); + if (signerkey == NULL) { + ret = HX509_PRIVATE_KEY_MISSING; + hx509_set_error_string(context, 0, ret, + "Private key missing for CRL signing"); + return ret; + } + + c.tbsCertList.version = malloc(sizeof(*c.tbsCertList.version)); + if (c.tbsCertList.version == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + + *c.tbsCertList.version = 1; + + ret = copy_AlgorithmIdentifier(sigalg, &c.tbsCertList.signature); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + + ret = copy_Name(&_hx509_get_cert(signer)->tbsCertificate.issuer, + &c.tbsCertList.issuer); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + + c.tbsCertList.thisUpdate.element = choice_Time_generalTime; + c.tbsCertList.thisUpdate.u.generalTime = time(NULL) - 24 * 3600; + + c.tbsCertList.nextUpdate = malloc(sizeof(*c.tbsCertList.nextUpdate)); + if (c.tbsCertList.nextUpdate == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + ret = ENOMEM; + goto out; + } + + { + time_t next = crl->expire; + if (next == 0) + next = time(NULL) + 24 * 3600 * 365; + + c.tbsCertList.nextUpdate->element = choice_Time_generalTime; + c.tbsCertList.nextUpdate->u.generalTime = next; + } + + c.tbsCertList.revokedCertificates = + calloc(1, sizeof(*c.tbsCertList.revokedCertificates)); + if (c.tbsCertList.revokedCertificates == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + ret = ENOMEM; + goto out; + } + c.tbsCertList.crlExtensions = NULL; + + ret = hx509_certs_iter_f(context, crl->revoked, add_revoked, &c.tbsCertList); + if (ret) + goto out; + + /* if not revoked certs, remove OPTIONAL entry */ + if (c.tbsCertList.revokedCertificates->len == 0) { + free(c.tbsCertList.revokedCertificates); + c.tbsCertList.revokedCertificates = NULL; + } + + ASN1_MALLOC_ENCODE(TBSCRLCertList, os->data, os->length, + &c.tbsCertList, &size, ret); + if (ret) { + hx509_set_error_string(context, 0, ret, "failed to encode tbsCRL"); + goto out; + } + if (size != os->length) + _hx509_abort("internal ASN.1 encoder error"); + + + ret = _hx509_create_signature_bitstring(context, + signerkey, + sigalg, + os, + &c.signatureAlgorithm, + &c.signatureValue); + free(os->data); + if (ret) { + hx509_set_error_string(context, 0, ret, "Failed to sign CRL"); + goto out; + } + + ASN1_MALLOC_ENCODE(CRLCertificateList, os->data, os->length, + &c, &size, ret); + if (ret) { + hx509_set_error_string(context, 0, ret, "failed to encode CRL"); + goto out; + } + if (size != os->length) + _hx509_abort("internal ASN.1 encoder error"); + + free_CRLCertificateList(&c); + + return 0; + +out: + free_CRLCertificateList(&c); + return ret; +} diff --git a/third_party/heimdal/lib/hx509/sel-gram.y b/third_party/heimdal/lib/hx509/sel-gram.y new file mode 100644 index 0000000..09f641d --- /dev/null +++ b/third_party/heimdal/lib/hx509/sel-gram.y @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2017 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +%{ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <hx_locl.h> + +#if !defined(yylex) +#define yylex _hx509_sel_yylex +#define yywrap _hx509_sel_yywrap +#endif +#if !defined(yyparse) +#define yyparse _hx509_sel_yyparse +#define yyerror _hx509_sel_yyerror +#define yylval _hx509_sel_yylval +#define yychar _hx509_sel_yychar +#define yydebug _hx509_sel_yydebug +#define yynerrs _hx509_sel_yynerrs +#endif + +%} + +%union { + char *string; + struct hx_expr *expr; +} + +%token kw_TRUE +%token kw_FALSE +%token kw_AND +%token kw_OR +%token kw_IN +%token kw_TAILMATCH + +%type <expr> expr +%type <expr> comp +%type <expr> word words +%type <expr> number +%type <expr> string +%type <expr> function +%type <expr> variable variables + +%token <string> NUMBER +%token <string> STRING +%token <string> IDENTIFIER + +%left '!' +%left kw_AND +%left kw_OR + +%start start + +%% + +start: expr { _hx509_expr_input.expr = $1; } + +expr : kw_TRUE { $$ = _hx509_make_expr(op_TRUE, NULL, NULL); } + | kw_FALSE { $$ = _hx509_make_expr(op_FALSE, NULL, NULL); } + | '!' expr { $$ = _hx509_make_expr(op_NOT, $2, NULL); } + | expr kw_AND expr { $$ = _hx509_make_expr(op_AND, $1, $3); } + | expr kw_OR expr { $$ = _hx509_make_expr(op_OR, $1, $3); } + | '(' expr ')' { $$ = $2; } + | comp { $$ = _hx509_make_expr(op_COMP, $1, NULL); } + ; + +words : word { $$ = _hx509_make_expr(expr_WORDS, $1, NULL); } + | word ',' words { $$ = _hx509_make_expr(expr_WORDS, $1, $3); } + ; + +comp : word '=' '=' word { $$ = _hx509_make_expr(comp_EQ, $1, $4); } + | word '!' '=' word { $$ = _hx509_make_expr(comp_NE, $1, $4); } + | word kw_TAILMATCH word { $$ = _hx509_make_expr(comp_TAILEQ, $1, $3); } + | word kw_IN '(' words ')' { $$ = _hx509_make_expr(comp_IN, $1, $4); } + | word kw_IN variable { $$ = _hx509_make_expr(comp_IN, $1, $3); } + ; + +word : number { $$ = $1; } + | string { $$ = $1; } + | function { $$ = $1; } + | variable { $$ = $1; } + ; + +number : NUMBER { $$ = _hx509_make_expr(expr_NUMBER, $1, NULL); }; +string : STRING { $$ = _hx509_make_expr(expr_STRING, $1, NULL); }; + +function: IDENTIFIER '(' words ')' { + $$ = _hx509_make_expr(expr_FUNCTION, $1, $3); } + ; +variable: '%' '{' variables '}' { $$ = $3; } + ; + +variables: IDENTIFIER '.' variables { + $$ = _hx509_make_expr(expr_VAR, $1, $3); } + | IDENTIFIER { + $$ = _hx509_make_expr(expr_VAR, $1, NULL); } + ; diff --git a/third_party/heimdal/lib/hx509/sel-lex.l b/third_party/heimdal/lib/hx509/sel-lex.l new file mode 100644 index 0000000..f401e40 --- /dev/null +++ b/third_party/heimdal/lib/hx509/sel-lex.l @@ -0,0 +1,148 @@ +%{ +/* + * Copyright (c) 2004 - 2017 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id$ */ + +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wunused-function" +#endif + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#undef ECHO + +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <stdlib.h> +#include "sel.h" +#include "sel-gram.h" +unsigned lineno = 1; + +static char * handle_string(void); +static int lex_input(char *, int); + +struct hx_expr_input _hx509_expr_input; + +#ifndef YY_NULL +#define YY_NULL 0 +#endif + +#define YY_NO_UNPUT 1 + +#undef YY_INPUT +#define YY_INPUT(buf,res,maxsize) (res = lex_input(buf, maxsize)) + +#undef ECHO + +%} +%% + +TRUE { return kw_TRUE; } +FALSE { return kw_FALSE; } +AND { return kw_AND; } +OR { return kw_OR; } +IN { return kw_IN; } +TAILMATCH { return kw_TAILMATCH; } + +[A-Za-z][-A-Za-z0-9_]* { + yylval.string = strdup ((const char *)yytext); + return IDENTIFIER; + } +"\"" { yylval.string = handle_string(); return STRING; } +\n { ++lineno; } +[,.!={}()%] { return *yytext; } +[ \t] ; +%% + +static char * +handle_string(void) +{ + char x[1024]; + int i = 0; + int c; + int quote = 0; + while((c = input()) != EOF){ + if(quote) { + x[i++] = '\\'; + x[i++] = c; + quote = 0; + continue; + } + if(c == '\n'){ + _hx509_sel_yyerror("unterminated string"); + lineno++; + break; + } + if(c == '\\'){ + quote++; + continue; + } + if(c == '\"') + break; + x[i++] = c; + } + x[i] = '\0'; + return strdup(x); +} + +#if !defined(yywrap) +#define yywrap _hx509_sel_yywrap +#endif + +int +yywrap () +{ + return 1; +} + +static int +lex_input(char *buf, int max_size) +{ + int n; + + n = _hx509_expr_input.length - _hx509_expr_input.offset; + if (max_size < n) + n = max_size; + if (n <= 0) + return YY_NULL; + + memcpy(buf, _hx509_expr_input.buf + _hx509_expr_input.offset, n); + _hx509_expr_input.offset += n; + + return n; +} diff --git a/third_party/heimdal/lib/hx509/sel.c b/third_party/heimdal/lib/hx509/sel.c new file mode 100644 index 0000000..bfd55e9 --- /dev/null +++ b/third_party/heimdal/lib/hx509/sel.c @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" + +HX509_LIB_FUNCTION struct hx_expr * HX509_LIB_CALL +_hx509_make_expr(enum hx_expr_op op, void *arg1, void *arg2) +{ + struct hx_expr *expr; + + expr = malloc(sizeof(*expr)); + if (expr == NULL) + return NULL; + expr->op = op; + expr->arg1 = arg1; + expr->arg2 = arg2; + + return expr; +} + +static const char * +eval_word(hx509_context context, hx509_env env, struct hx_expr *word) +{ + switch (word->op) { + case expr_STRING: + return word->arg1; + case expr_VAR: + if (word->arg2 == NULL) + return hx509_env_find(context, env, word->arg1); + + env = hx509_env_find_binding(context, env, word->arg1); + if (env == NULL) + return NULL; + + return eval_word(context, env, word->arg2); + default: + return NULL; + } +} + +static hx509_env +find_variable(hx509_context context, hx509_env env, struct hx_expr *word) +{ + assert(word->op == expr_VAR); + + if (word->arg2 == NULL) + return hx509_env_find_binding(context, env, word->arg1); + + env = hx509_env_find_binding(context, env, word->arg1); + if (env == NULL) + return NULL; + return find_variable(context, env, word->arg2); +} + +static int +eval_comp(hx509_context context, hx509_env env, struct hx_expr *expr) +{ + switch (expr->op) { + case comp_NE: + case comp_EQ: + case comp_TAILEQ: { + const char *s1, *s2; + int ret; + + s1 = eval_word(context, env, expr->arg1); + s2 = eval_word(context, env, expr->arg2); + + if (s1 == NULL || s2 == NULL) + return FALSE; + + if (expr->op == comp_TAILEQ) { + size_t len1 = strlen(s1); + size_t len2 = strlen(s2); + + if (len1 < len2) + return 0; + ret = strcmp(s1 + (len1 - len2), s2) == 0; + } else { + ret = strcmp(s1, s2) == 0; + if (expr->op == comp_NE) + ret = !ret; + } + return ret; + } + case comp_IN: { + struct hx_expr *subexpr; + const char *w, *s1; + + w = eval_word(context, env, expr->arg1); + + subexpr = expr->arg2; + + if (subexpr->op == expr_WORDS) { + while (subexpr) { + s1 = eval_word(context, env, subexpr->arg1); + if (strcmp(w, s1) == 0) + return TRUE; + subexpr = subexpr->arg2; + } + } else if (subexpr->op == expr_VAR) { + hx509_env subenv; + + subenv = find_variable(context, env, subexpr); + if (subenv == NULL) + return FALSE; + + while (subenv) { + if (subenv->type != env_string) + continue; + if (strcmp(w, subenv->name) == 0) + return TRUE; + if (strcmp(w, subenv->u.string) == 0) + return TRUE; + subenv = subenv->next; + } + + } else + _hx509_abort("hx509 eval IN unknown op: %d", (int)subexpr->op); + + return FALSE; + } + default: + _hx509_abort("hx509 eval expr with unknown op: %d", (int)expr->op); + } + return FALSE; +} + +HX509_LIB_FUNCTION int HX509_LIB_CALL +_hx509_expr_eval(hx509_context context, hx509_env env, struct hx_expr *expr) +{ + switch (expr->op) { + case op_TRUE: + return 1; + case op_FALSE: + return 0; + case op_NOT: + return ! _hx509_expr_eval(context, env, expr->arg1); + case op_AND: + return _hx509_expr_eval(context, env, expr->arg1) && + _hx509_expr_eval(context, env, expr->arg2); + case op_OR: + return _hx509_expr_eval(context, env, expr->arg1) || + _hx509_expr_eval(context, env, expr->arg2); + case op_COMP: + return eval_comp(context, env, expr->arg1); + default: + _hx509_abort("hx509 eval expr with unknown op: %d", (int)expr->op); + UNREACHABLE(return 0); + } +} + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_expr_free(struct hx_expr *expr) +{ + switch (expr->op) { + case expr_STRING: + case expr_NUMBER: + free(expr->arg1); + break; + case expr_WORDS: + case expr_FUNCTION: + case expr_VAR: + free(expr->arg1); + if (expr->arg2) + _hx509_expr_free(expr->arg2); + break; + default: + if (expr->arg1) + _hx509_expr_free(expr->arg1); + if (expr->arg2) + _hx509_expr_free(expr->arg2); + break; + } + free(expr); +} + +/* XXX Horrible, no good cause not thread-safe */ +HX509_LIB_FUNCTION struct hx_expr * HX509_LIB_CALL +_hx509_expr_parse(const char *buf) +{ + _hx509_expr_input.buf = buf; + _hx509_expr_input.length = strlen(buf); + _hx509_expr_input.offset = 0; + _hx509_expr_input.expr = NULL; + + if (_hx509_expr_input.error) { + free(_hx509_expr_input.error); + _hx509_expr_input.error = NULL; + } + + yyparse(); + + return _hx509_expr_input.expr; +} + +const char * +_hx509_expr_parse_error(void) +{ + return _hx509_expr_input.error; +} + +void +_hx509_sel_yyerror (const char *s) +{ + if (_hx509_expr_input.error) + free(_hx509_expr_input.error); + + _hx509_expr_input.error = strdup(s); +} + diff --git a/third_party/heimdal/lib/hx509/sel.h b/third_party/heimdal/lib/hx509/sel.h new file mode 100644 index 0000000..daa471e --- /dev/null +++ b/third_party/heimdal/lib/hx509/sel.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +enum hx_expr_op { + op_TRUE, + op_FALSE, + op_NOT, + op_AND, + op_OR, + op_COMP, + + comp_EQ, + comp_NE, + comp_IN, + comp_TAILEQ, + + expr_NUMBER, + expr_STRING, + expr_FUNCTION, + expr_VAR, + expr_WORDS +}; + +struct hx_expr { + enum hx_expr_op op; + void *arg1; + void *arg2; +}; + +struct hx_expr_input { + const char *buf; + size_t length; + size_t offset; + struct hx_expr *expr; + char *error; +}; + +extern struct hx_expr_input _hx509_expr_input; + +/* + * With bison/flex, the more modern way to allow multiple yacc/lex grammars to + * be linked into a single executable is to use the + * + * bison: -p, --name-prefix=,PREFIX/, -Dapi.prefix=PREFIX + * flex: -Pprefix, --prefix=STRING + * + * options, these take care of renaming all the machine-generated global entry + * points, some of which are new. When these options are used "yylex", + * "yyparse", ... are already defined and our (potentially incomplete) attempt + * to do the same conflicts with the "right" new way to handle this. The below + * logic gets us out of the way when the job has already been taken care of by + * the parser-generator. + */ +#if !defined(yylex) +#define yylex _hx509_sel_yylex +#define yywrap _hx509_sel_yywrap +#endif +#if !defined(yyparse) +#define yyparse _hx509_sel_yyparse +#define yyerror _hx509_sel_yyerror +#define yylval _hx509_sel_yylval +#define yychar _hx509_sel_yychar +#define yydebug _hx509_sel_yydebug +#define yynerrs _hx509_sel_yynerrs +#endif + +int _hx509_sel_yyparse(void); +int _hx509_sel_yylex(void); +void _hx509_sel_yyerror(const char *); + diff --git a/third_party/heimdal/lib/hx509/softp11.c b/third_party/heimdal/lib/hx509/softp11.c new file mode 100644 index 0000000..75f6755 --- /dev/null +++ b/third_party/heimdal/lib/hx509/softp11.c @@ -0,0 +1,1777 @@ +/* + * Copyright (c) 2004 - 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define CRYPTOKI_EXPORTS 1 + +#include "hx_locl.h" +#include "ref/pkcs11.h" + +#define OBJECT_ID_MASK 0xfff +#define HANDLE_OBJECT_ID(h) ((h) & OBJECT_ID_MASK) +#define OBJECT_ID(obj) HANDLE_OBJECT_ID((obj)->object_handle) + +#ifndef HAVE_RANDOM +#define random() rand() +#define srandom(s) srand(s) +#endif + +#ifdef _WIN32 +#include <shlobj.h> +#endif + +struct st_attr { + CK_ATTRIBUTE attribute; + int secret; +}; + +struct st_object { + CK_OBJECT_HANDLE object_handle; + struct st_attr *attrs; + int num_attributes; + hx509_cert cert; +}; + +static struct soft_token { + CK_VOID_PTR application; + CK_NOTIFY notify; + char *config_file; + hx509_certs certs; + struct { + struct st_object **objs; + int num_objs; + } object; + struct { + int hardware_slot; + int app_error_fatal; + int login_done; + } flags; + int open_sessions; + struct session_state { + CK_SESSION_HANDLE session_handle; + + struct { + CK_ATTRIBUTE *attributes; + CK_ULONG num_attributes; + int next_object; + } find; + + int sign_object; + CK_MECHANISM_PTR sign_mechanism; + int verify_object; + CK_MECHANISM_PTR verify_mechanism; + } state[10]; +#define MAX_NUM_SESSION (sizeof(soft_token.state)/sizeof(soft_token.state[0])) + FILE *logfile; +} soft_token; + +static hx509_context context; + +static void +application_error(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + if (soft_token.flags.app_error_fatal) + abort(); +} + +static void +st_logf(const char *fmt, ...) +{ + va_list ap; + if (soft_token.logfile == NULL) + return; + va_start(ap, fmt); + vfprintf(soft_token.logfile, fmt, ap); + va_end(ap); + fflush(soft_token.logfile); +} + +static CK_RV +init_context(void) +{ + if (context == NULL) { + int ret = hx509_context_init(&context); + if (ret) + return CKR_GENERAL_ERROR; + } + return CKR_OK; +} + +#define INIT_CONTEXT() { CK_RV icret = init_context(); if (icret) return icret; } + +static void +snprintf_fill(char *str, size_t size, char fillchar, const char *fmt, ...) +{ + int len; + va_list ap; + va_start(ap, fmt); + len = vsnprintf(str, size, fmt, ap); + va_end(ap); + if (len < 0 || (size_t)len > size) + return; + while ((size_t)len < size) + str[len++] = fillchar; +} + +#ifndef TEST_APP +#define printf error_use_st_logf +#endif + +#define VERIFY_SESSION_HANDLE(s, state) \ +{ \ + CK_RV xret; \ + xret = verify_session_handle(s, state); \ + if (xret != CKR_OK) { \ + /* return CKR_OK */; \ + } \ +} + +static CK_RV +verify_session_handle(CK_SESSION_HANDLE hSession, + struct session_state **state) +{ + size_t i; + + for (i = 0; i < MAX_NUM_SESSION; i++){ + if (soft_token.state[i].session_handle == hSession) + break; + } + if (i == MAX_NUM_SESSION) { + application_error("use of invalid handle: 0x%08lx\n", + (unsigned long)hSession); + return CKR_SESSION_HANDLE_INVALID; + } + if (state) + *state = &soft_token.state[i]; + return CKR_OK; +} + +static CK_RV +object_handle_to_object(CK_OBJECT_HANDLE handle, + struct st_object **object) +{ + int i = HANDLE_OBJECT_ID(handle); + + *object = NULL; + if (i >= soft_token.object.num_objs) + return CKR_ARGUMENTS_BAD; + if (soft_token.object.objs[i] == NULL) + return CKR_ARGUMENTS_BAD; + if (soft_token.object.objs[i]->object_handle != handle) + return CKR_ARGUMENTS_BAD; + *object = soft_token.object.objs[i]; + return CKR_OK; +} + +static int +attributes_match(const struct st_object *obj, + const CK_ATTRIBUTE *attributes, + CK_ULONG num_attributes) +{ + CK_ULONG i; + int j; + + st_logf("attributes_match: %ld\n", (unsigned long)OBJECT_ID(obj)); + + for (i = 0; i < num_attributes; i++) { + int match = 0; + for (j = 0; j < obj->num_attributes; j++) { + if (attributes[i].type == obj->attrs[j].attribute.type && + attributes[i].ulValueLen == obj->attrs[j].attribute.ulValueLen && + memcmp(attributes[i].pValue, obj->attrs[j].attribute.pValue, + attributes[i].ulValueLen) == 0) { + match = 1; + break; + } + } + if (match == 0) { + st_logf("type %d attribute have no match\n", attributes[i].type); + return 0; + } + } + st_logf("attribute matches\n"); + return 1; +} + +static void +print_attributes(const CK_ATTRIBUTE *attributes, + CK_ULONG num_attributes) +{ + CK_ULONG i; + + st_logf("find objects: attrs: %lu\n", (unsigned long)num_attributes); + + for (i = 0; i < num_attributes; i++) { + st_logf(" type: "); + switch (attributes[i].type) { + case CKA_TOKEN: { + CK_BBOOL *ck_true; + if (attributes[i].ulValueLen != sizeof(CK_BBOOL)) { + application_error("token attribute wrong length\n"); + break; + } + ck_true = attributes[i].pValue; + st_logf("token: %s", *ck_true ? "TRUE" : "FALSE"); + break; + } + case CKA_CLASS: { + CK_OBJECT_CLASS *class; + if (attributes[i].ulValueLen != sizeof(CK_ULONG)) { + application_error("class attribute wrong length\n"); + break; + } + class = attributes[i].pValue; + st_logf("class "); + switch (*class) { + case CKO_CERTIFICATE: + st_logf("certificate"); + break; + case CKO_PUBLIC_KEY: + st_logf("public key"); + break; + case CKO_PRIVATE_KEY: + st_logf("private key"); + break; + case CKO_SECRET_KEY: + st_logf("secret key"); + break; + case CKO_DOMAIN_PARAMETERS: + st_logf("domain parameters"); + break; + default: + st_logf("[class %lx]", (long unsigned)*class); + break; + } + break; + } + case CKA_PRIVATE: + st_logf("private"); + break; + case CKA_LABEL: + st_logf("label"); + break; + case CKA_APPLICATION: + st_logf("application"); + break; + case CKA_VALUE: + st_logf("value"); + break; + case CKA_ID: + st_logf("id"); + break; + default: + st_logf("[unknown 0x%08lx]", (unsigned long)attributes[i].type); + break; + } + st_logf("\n"); + } +} + +static struct st_object * +add_st_object(void) +{ + struct st_object *o, **objs; + int i; + + o = calloc(1, sizeof(*o)); + if (o == NULL) + return NULL; + + for (i = 0; i < soft_token.object.num_objs; i++) { + if (soft_token.object.objs[i] == NULL) { + soft_token.object.objs[i] = o; + break; + } + } + if (i == soft_token.object.num_objs) { + objs = realloc(soft_token.object.objs, + (soft_token.object.num_objs + 1) * sizeof(soft_token.object.objs[0])); + if (objs == NULL) { + free(o); + return NULL; + } + soft_token.object.objs = objs; + soft_token.object.objs[soft_token.object.num_objs++] = o; + } + soft_token.object.objs[i]->object_handle = + (random() & (~OBJECT_ID_MASK)) | i; + + return o; +} + +static CK_RV +add_object_attribute(struct st_object *o, + int secret, + CK_ATTRIBUTE_TYPE type, + CK_VOID_PTR pValue, + CK_ULONG ulValueLen) +{ + struct st_attr *a; + int i; + + if (pValue == NULL && ulValueLen) + return CKR_ARGUMENTS_BAD; + + i = o->num_attributes; + a = realloc(o->attrs, (i + 1) * sizeof(o->attrs[0])); + if (a == NULL) + return CKR_DEVICE_MEMORY; + o->attrs = a; + o->attrs[i].secret = secret; + o->attrs[i].attribute.type = type; + o->attrs[i].attribute.pValue = malloc(ulValueLen); + if (o->attrs[i].attribute.pValue == NULL && ulValueLen != 0) + return CKR_DEVICE_MEMORY; + if (ulValueLen) + memcpy(o->attrs[i].attribute.pValue, pValue, ulValueLen); + o->attrs[i].attribute.ulValueLen = ulValueLen; + o->num_attributes++; + + return CKR_OK; +} + +static CK_RV +add_pubkey_info(hx509_context hxctx, struct st_object *o, + CK_KEY_TYPE key_type, hx509_cert cert) +{ + BIGNUM *num; + CK_BYTE *modulus = NULL; + size_t modulus_len = 0; + CK_ULONG modulus_bits = 0; + CK_BYTE *exponent = NULL; + size_t exponent_len = 0; + + if (key_type != CKK_RSA) + return CKR_OK; + if (_hx509_cert_private_key(cert) == NULL) + return CKR_OK; + + num = _hx509_private_key_get_internal(context, + _hx509_cert_private_key(cert), + "rsa-modulus"); + if (num == NULL) + return CKR_GENERAL_ERROR; + modulus_bits = BN_num_bits(num); + + modulus_len = BN_num_bytes(num); + modulus = malloc(modulus_len); + BN_bn2bin(num, modulus); + BN_free(num); + + add_object_attribute(o, 0, CKA_MODULUS, modulus, modulus_len); + add_object_attribute(o, 0, CKA_MODULUS_BITS, + &modulus_bits, sizeof(modulus_bits)); + + free(modulus); + + num = _hx509_private_key_get_internal(context, + _hx509_cert_private_key(cert), + "rsa-exponent"); + if (num == NULL) + return CKR_GENERAL_ERROR; + + exponent_len = BN_num_bytes(num); + exponent = malloc(exponent_len); + BN_bn2bin(num, exponent); + BN_free(num); + + add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT, + exponent, exponent_len); + + free(exponent); + + return CKR_OK; +} + + +struct foo { + char *label; + char *id; +}; + +static int HX509_LIB_CALL +add_cert(hx509_context hxctx, void *ctx, hx509_cert cert) +{ + static char empty[] = ""; + struct foo *foo = (struct foo *)ctx; + struct st_object *o = NULL; + CK_OBJECT_CLASS type; + CK_BBOOL bool_true = CK_TRUE; + CK_BBOOL bool_false = CK_FALSE; + CK_CERTIFICATE_TYPE cert_type = CKC_X_509; + CK_KEY_TYPE key_type; + CK_MECHANISM_TYPE mech_type; + CK_RV ret = CKR_GENERAL_ERROR; + int hret; + heim_octet_string cert_data, subject_data, issuer_data, serial_data; + + st_logf("adding certificate\n"); + + serial_data.data = NULL; + serial_data.length = 0; + cert_data = subject_data = issuer_data = serial_data; + + hret = hx509_cert_binary(hxctx, cert, &cert_data); + if (hret) + goto out; + + { + hx509_name name; + + hret = hx509_cert_get_issuer(cert, &name); + if (hret) + goto out; + hret = hx509_name_binary(name, &issuer_data); + hx509_name_free(&name); + if (hret) + goto out; + + hret = hx509_cert_get_subject(cert, &name); + if (hret) + goto out; + hret = hx509_name_binary(name, &subject_data); + hx509_name_free(&name); + if (hret) + goto out; + } + + { + AlgorithmIdentifier alg; + + hret = hx509_cert_get_SPKI_AlgorithmIdentifier(context, cert, &alg); + if (hret) { + ret = CKR_DEVICE_MEMORY; + goto out; + } + + key_type = CKK_RSA; /* XXX */ + + free_AlgorithmIdentifier(&alg); + } + + + type = CKO_CERTIFICATE; + o = add_st_object(); + if (o == NULL) { + ret = CKR_DEVICE_MEMORY; + goto out; + } + + o->cert = hx509_cert_ref(cert); + + add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type)); + add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label)); + + add_object_attribute(o, 0, CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type)); + add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id)); + + add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length); + add_object_attribute(o, 0, CKA_ISSUER, issuer_data.data, issuer_data.length); + add_object_attribute(o, 0, CKA_SERIAL_NUMBER, serial_data.data, serial_data.length); + add_object_attribute(o, 0, CKA_VALUE, cert_data.data, cert_data.length); + add_object_attribute(o, 0, CKA_TRUSTED, &bool_false, sizeof(bool_false)); + + st_logf("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o)); + + type = CKO_PUBLIC_KEY; + o = add_st_object(); + if (o == NULL) { + ret = CKR_DEVICE_MEMORY; + goto out; + } + o->cert = hx509_cert_ref(cert); + + add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type)); + add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label)); + + add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type)); + add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id)); + add_object_attribute(o, 0, CKA_START_DATE, empty, 1); /* XXX */ + add_object_attribute(o, 0, CKA_END_DATE, empty, 1); /* XXX */ + add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false)); + mech_type = CKM_RSA_X_509; + add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type)); + + add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length); + add_object_attribute(o, 0, CKA_ENCRYPT, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_VERIFY, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_VERIFY_RECOVER, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_WRAP, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true)); + + add_pubkey_info(hxctx, o, key_type, cert); + + st_logf("add key ok: %lx\n", (unsigned long)OBJECT_ID(o)); + + if (hx509_cert_have_private_key(cert)) { + CK_FLAGS flags; + + type = CKO_PRIVATE_KEY; + + /* Note to static analyzers: `o' is still referred to via globals */ + o = add_st_object(); + if (o == NULL) { + ret = CKR_DEVICE_MEMORY; + goto out; + } + o->cert = hx509_cert_ref(cert); + + add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type)); + add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_PRIVATE, &bool_true, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label)); + + add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type)); + add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id)); + add_object_attribute(o, 0, CKA_START_DATE, empty, 1); /* XXX */ + add_object_attribute(o, 0, CKA_END_DATE, empty, 1); /* XXX */ + add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false)); + mech_type = CKM_RSA_X_509; + add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type)); + + add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length); + add_object_attribute(o, 0, CKA_SENSITIVE, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_SECONDARY_AUTH, &bool_false, sizeof(bool_true)); + flags = 0; + add_object_attribute(o, 0, CKA_AUTH_PIN_FLAGS, &flags, sizeof(flags)); + + add_object_attribute(o, 0, CKA_DECRYPT, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_SIGN, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_SIGN_RECOVER, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_UNWRAP, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_EXTRACTABLE, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_NEVER_EXTRACTABLE, &bool_false, sizeof(bool_false)); + + add_pubkey_info(hxctx, o, key_type, cert); + } + + ret = CKR_OK; + out: + if (ret != CKR_OK) { + st_logf("something went wrong when adding cert!\n"); + + /* XXX wack o */; + } + hx509_xfree(cert_data.data); + hx509_xfree(serial_data.data); + hx509_xfree(issuer_data.data); + hx509_xfree(subject_data.data); + + /* Note to static analyzers: `o' is still referred to via globals */ + return 0; +} + +static CK_RV +add_certificate(const char *cert_file, + const char *pin, + char *id, + char *label) +{ + hx509_certs certs; + hx509_lock lock = NULL; + int ret, flags = 0; + + struct foo foo; + foo.id = id; + foo.label = label; + + if (pin == NULL) + flags |= HX509_CERTS_UNPROTECT_ALL; + + if (pin) { + char *str; + ret = asprintf(&str, "PASS:%s", pin); + if (ret == -1 || !str) { + st_logf("failed to allocate memory\n"); + return CKR_GENERAL_ERROR; + } + + hx509_lock_init(context, &lock); + hx509_lock_command_string(lock, str); + + memset(str, 0, strlen(str)); + free(str); + } + + ret = hx509_certs_init(context, cert_file, flags, lock, &certs); + if (ret) { + st_logf("failed to open file %s\n", cert_file); + return CKR_GENERAL_ERROR; + } + + ret = hx509_certs_iter_f(context, certs, add_cert, &foo); + hx509_certs_free(&certs); + if (ret) { + st_logf("failed adding certs from file %s\n", cert_file); + return CKR_GENERAL_ERROR; + } + + return CKR_OK; +} + +static void +find_object_final(struct session_state *state) +{ + if (state->find.attributes) { + CK_ULONG i; + + for (i = 0; i < state->find.num_attributes; i++) { + if (state->find.attributes[i].pValue) + free(state->find.attributes[i].pValue); + } + free(state->find.attributes); + state->find.attributes = NULL; + state->find.num_attributes = 0; + state->find.next_object = -1; + } +} + +static void +reset_crypto_state(struct session_state *state) +{ + state->sign_object = -1; + if (state->sign_mechanism) + free(state->sign_mechanism); + state->sign_mechanism = NULL_PTR; + state->verify_object = -1; + if (state->verify_mechanism) + free(state->verify_mechanism); + state->verify_mechanism = NULL_PTR; +} + +static void +close_session(struct session_state *state) +{ + if (state->find.attributes) { + application_error("application didn't do C_FindObjectsFinal\n"); + find_object_final(state); + } + + state->session_handle = CK_INVALID_HANDLE; + soft_token.application = NULL_PTR; + soft_token.notify = NULL_PTR; + reset_crypto_state(state); +} + +static const char * +has_session(void) +{ + return soft_token.open_sessions > 0 ? "yes" : "no"; +} + +static CK_RV +read_conf_file(const char *fn, CK_USER_TYPE userType, const char *pin) +{ + char buf[1024], *type, *s, *p; + FILE *f; + CK_RV ret = CKR_OK; + CK_RV failed = CKR_OK; + + if (fn == NULL) { + st_logf("Can't open configuration file. No file specified\n"); + return CKR_GENERAL_ERROR; + } + + f = fopen(fn, "r"); + if (f == NULL) { + st_logf("can't open configuration file %s\n", fn); + return CKR_GENERAL_ERROR; + } + rk_cloexec_file(f); + + while(fgets(buf, sizeof(buf), f) != NULL) { + buf[strcspn(buf, "\n")] = '\0'; + + st_logf("line: %s\n", buf); + + p = buf; + while (isspace((unsigned char)*p)) + p++; + if (*p == '#') + continue; + while (isspace((unsigned char)*p)) + p++; + + s = NULL; + type = strtok_r(p, "\t", &s); + if (type == NULL) + continue; + + if (strcasecmp("certificate", type) == 0) { + char *cert, *id, *label; + + id = strtok_r(NULL, "\t", &s); + if (id == NULL) { + st_logf("no id\n"); + continue; + } + st_logf("id: %s\n", id); + label = strtok_r(NULL, "\t", &s); + if (label == NULL) { + st_logf("no label\n"); + continue; + } + cert = strtok_r(NULL, "\t", &s); + if (cert == NULL) { + st_logf("no certfiicate store\n"); + continue; + } + + st_logf("adding: %s: %s in file %s\n", id, label, cert); + + ret = add_certificate(cert, pin, id, label); + if (ret) + failed = ret; + } else if (strcasecmp("debug", type) == 0) { + char *name; + + name = strtok_r(NULL, "\t", &s); + if (name == NULL) { + st_logf("no filename\n"); + continue; + } + + if (soft_token.logfile) + fclose(soft_token.logfile); + + if (strcasecmp(name, "stdout") == 0) + soft_token.logfile = stdout; + else { + soft_token.logfile = fopen(name, "a"); + if (soft_token.logfile) + rk_cloexec_file(soft_token.logfile); + } + if (soft_token.logfile == NULL) + st_logf("failed to open file: %s\n", name); + + } else if (strcasecmp("app-fatal", type) == 0) { + char *name; + + name = strtok_r(NULL, "\t", &s); + if (name == NULL) { + st_logf("argument to app-fatal\n"); + continue; + } + + if (strcmp(name, "true") == 0 || strcmp(name, "on") == 0) + soft_token.flags.app_error_fatal = 1; + else if (strcmp(name, "false") == 0 || strcmp(name, "off") == 0) + soft_token.flags.app_error_fatal = 0; + else + st_logf("unknown app-fatal: %s\n", name); + + } else { + st_logf("unknown type: %s\n", type); + } + } + + fclose(f); + + return failed; +} + +static CK_RV +func_not_supported(void) +{ + st_logf("function not supported\n"); + return CKR_FUNCTION_NOT_SUPPORTED; +} + +static char * +get_config_file_for_user(void) +{ + char *fn; + int ret; + + fn = secure_getenv("SOFTPKCS11RC"); + if (fn) + fn = strdup(fn); + if (fn == NULL) { + char homebuf[MAX_PATH]; + const char *home = roken_get_appdatadir(homebuf, sizeof(homebuf)); + + if (home) { + ret = asprintf(&fn, "%s/.soft-token.rc", home); + if (ret == -1) + fn = NULL; + } else { +#ifndef WIN32 + fn = strdup("/etc/soft-token.rc"); +#endif + } + } + + return fn; +} + + +CK_RV CK_SPEC +C_Initialize(CK_VOID_PTR a) +{ + CK_C_INITIALIZE_ARGS_PTR args = a; + CK_RV ret; + size_t i; + + st_logf("Initialize\n"); + + INIT_CONTEXT(); + + OpenSSL_add_all_algorithms(); + + srandom(getpid() ^ (int) time(NULL)); + + for (i = 0; i < MAX_NUM_SESSION; i++) { + soft_token.state[i].session_handle = CK_INVALID_HANDLE; + soft_token.state[i].find.attributes = NULL; + soft_token.state[i].find.num_attributes = 0; + soft_token.state[i].find.next_object = -1; + reset_crypto_state(&soft_token.state[i]); + } + + soft_token.flags.hardware_slot = 1; + soft_token.flags.app_error_fatal = 0; + soft_token.flags.login_done = 0; + + soft_token.object.objs = NULL; + soft_token.object.num_objs = 0; + + soft_token.logfile = NULL; +#if 0 + soft_token.logfile = stdout; +#endif +#if 0 + soft_token.logfile = fopen("/tmp/log-pkcs11.txt", "a"); +#endif + + if (a != NULL_PTR) { + st_logf("\tCreateMutex:\t%p\n", args->CreateMutex); + st_logf("\tDestroyMutext\t%p\n", args->DestroyMutex); + st_logf("\tLockMutext\t%p\n", args->LockMutex); + st_logf("\tUnlockMutext\t%p\n", args->UnlockMutex); + st_logf("\tFlags\t%04x\n", (unsigned int)args->flags); + } + + soft_token.config_file = get_config_file_for_user(); + + /* + * This operations doesn't return CKR_OK if any of the + * certificates failes to be unparsed (ie password protected). + */ + ret = read_conf_file(soft_token.config_file, CKU_USER, NULL); + if (ret == CKR_OK) + soft_token.flags.login_done = 1; + + return CKR_OK; +} + +CK_RV +C_Finalize(CK_VOID_PTR args) +{ + size_t i; + + INIT_CONTEXT(); + + st_logf("Finalize\n"); + + for (i = 0; i < MAX_NUM_SESSION; i++) { + if (soft_token.state[i].session_handle != CK_INVALID_HANDLE) { + application_error("application finalized without " + "closing session\n"); + close_session(&soft_token.state[i]); + } + } + + return CKR_OK; +} + +CK_RV +C_GetInfo(CK_INFO_PTR args) +{ + INIT_CONTEXT(); + + st_logf("GetInfo\n"); + + memset(args, 17, sizeof(*args)); + args->cryptokiVersion.major = 2; + args->cryptokiVersion.minor = 10; + snprintf_fill((char *)args->manufacturerID, + sizeof(args->manufacturerID), + ' ', + "Heimdal hx509 SoftToken"); + snprintf_fill((char *)args->libraryDescription, + sizeof(args->libraryDescription), ' ', + "Heimdal hx509 SoftToken"); + args->libraryVersion.major = 2; + args->libraryVersion.minor = 0; + + return CKR_OK; +} + +extern CK_FUNCTION_LIST funcs; + +CK_RV +C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) +{ + INIT_CONTEXT(); + + *ppFunctionList = &funcs; + return CKR_OK; +} + +CK_RV +C_GetSlotList(CK_BBOOL tokenPresent, + CK_SLOT_ID_PTR pSlotList, + CK_ULONG_PTR pulCount) +{ + INIT_CONTEXT(); + st_logf("GetSlotList: %s\n", + tokenPresent ? "tokenPresent" : "token not Present"); + if (pSlotList) + pSlotList[0] = 1; + *pulCount = 1; + return CKR_OK; +} + +CK_RV +C_GetSlotInfo(CK_SLOT_ID slotID, + CK_SLOT_INFO_PTR pInfo) +{ + INIT_CONTEXT(); + st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID, has_session()); + + memset(pInfo, 18, sizeof(*pInfo)); + + if (slotID != 1) + return CKR_ARGUMENTS_BAD; + + snprintf_fill((char *)pInfo->slotDescription, + sizeof(pInfo->slotDescription), + ' ', + "Heimdal hx509 SoftToken (slot)"); + snprintf_fill((char *)pInfo->manufacturerID, + sizeof(pInfo->manufacturerID), + ' ', + "Heimdal hx509 SoftToken (slot)"); + pInfo->flags = CKF_TOKEN_PRESENT; + if (soft_token.flags.hardware_slot) + pInfo->flags |= CKF_HW_SLOT; + pInfo->hardwareVersion.major = 1; + pInfo->hardwareVersion.minor = 0; + pInfo->firmwareVersion.major = 1; + pInfo->firmwareVersion.minor = 0; + + return CKR_OK; +} + +CK_RV +C_GetTokenInfo(CK_SLOT_ID slotID, + CK_TOKEN_INFO_PTR pInfo) +{ + INIT_CONTEXT(); + st_logf("GetTokenInfo: %s\n", has_session()); + + memset(pInfo, 19, sizeof(*pInfo)); + + snprintf_fill((char *)pInfo->label, + sizeof(pInfo->label), + ' ', + "Heimdal hx509 SoftToken (token)"); + snprintf_fill((char *)pInfo->manufacturerID, + sizeof(pInfo->manufacturerID), + ' ', + "Heimdal hx509 SoftToken (token)"); + snprintf_fill((char *)pInfo->model, + sizeof(pInfo->model), + ' ', + "Heimdal hx509 SoftToken (token)"); + snprintf_fill((char *)pInfo->serialNumber, + sizeof(pInfo->serialNumber), + ' ', + "4711"); + pInfo->flags = + CKF_TOKEN_INITIALIZED | + CKF_USER_PIN_INITIALIZED; + + if (soft_token.flags.login_done == 0) + pInfo->flags |= CKF_LOGIN_REQUIRED; + + /* CFK_RNG | + CKF_RESTORE_KEY_NOT_NEEDED | + */ + pInfo->ulMaxSessionCount = MAX_NUM_SESSION; + pInfo->ulSessionCount = soft_token.open_sessions; + pInfo->ulMaxRwSessionCount = MAX_NUM_SESSION; + pInfo->ulRwSessionCount = soft_token.open_sessions; + pInfo->ulMaxPinLen = 1024; + pInfo->ulMinPinLen = 0; + pInfo->ulTotalPublicMemory = 4711; + pInfo->ulFreePublicMemory = 4712; + pInfo->ulTotalPrivateMemory = 4713; + pInfo->ulFreePrivateMemory = 4714; + pInfo->hardwareVersion.major = 2; + pInfo->hardwareVersion.minor = 0; + pInfo->firmwareVersion.major = 2; + pInfo->firmwareVersion.minor = 0; + + return CKR_OK; +} + +CK_RV +C_GetMechanismList(CK_SLOT_ID slotID, + CK_MECHANISM_TYPE_PTR pMechanismList, + CK_ULONG_PTR pulCount) +{ + INIT_CONTEXT(); + st_logf("GetMechanismList\n"); + + *pulCount = 1; + if (pMechanismList == NULL_PTR) + return CKR_OK; + pMechanismList[0] = CKM_RSA_PKCS; + + return CKR_OK; +} + +CK_RV +C_GetMechanismInfo(CK_SLOT_ID slotID, + CK_MECHANISM_TYPE type, + CK_MECHANISM_INFO_PTR pInfo) +{ + INIT_CONTEXT(); + st_logf("GetMechanismInfo: slot %d type: %d\n", + (int)slotID, (int)type); + memset(pInfo, 0, sizeof(*pInfo)); + + return CKR_OK; +} + +CK_RV +C_InitToken(CK_SLOT_ID slotID, + CK_UTF8CHAR_PTR pPin, + CK_ULONG ulPinLen, + CK_UTF8CHAR_PTR pLabel) +{ + INIT_CONTEXT(); + st_logf("InitToken: slot %d\n", (int)slotID); + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +C_OpenSession(CK_SLOT_ID slotID, + CK_FLAGS flags, + CK_VOID_PTR pApplication, + CK_NOTIFY Notify, + CK_SESSION_HANDLE_PTR phSession) +{ + size_t i; + INIT_CONTEXT(); + st_logf("OpenSession: slot: %d\n", (int)slotID); + + if (soft_token.open_sessions == MAX_NUM_SESSION) + return CKR_SESSION_COUNT; + + soft_token.application = pApplication; + soft_token.notify = Notify; + + for (i = 0; i < MAX_NUM_SESSION; i++) + if (soft_token.state[i].session_handle == CK_INVALID_HANDLE) + break; + if (i == MAX_NUM_SESSION) + abort(); + + soft_token.open_sessions++; + + soft_token.state[i].session_handle = + (CK_SESSION_HANDLE)(random() & 0xfffff); + *phSession = soft_token.state[i].session_handle; + + return CKR_OK; +} + +CK_RV +C_CloseSession(CK_SESSION_HANDLE hSession) +{ + struct session_state *state; + INIT_CONTEXT(); + st_logf("CloseSession\n"); + + if (verify_session_handle(hSession, &state) != CKR_OK) + application_error("closed session not open"); + else + close_session(state); + + return CKR_OK; +} + +CK_RV +C_CloseAllSessions(CK_SLOT_ID slotID) +{ + size_t i; + INIT_CONTEXT(); + + st_logf("CloseAllSessions\n"); + + for (i = 0; i < MAX_NUM_SESSION; i++) + if (soft_token.state[i].session_handle != CK_INVALID_HANDLE) + close_session(&soft_token.state[i]); + + return CKR_OK; +} + +CK_RV +C_GetSessionInfo(CK_SESSION_HANDLE hSession, + CK_SESSION_INFO_PTR pInfo) +{ + st_logf("GetSessionInfo\n"); + INIT_CONTEXT(); + + VERIFY_SESSION_HANDLE(hSession, NULL); + + memset(pInfo, 20, sizeof(*pInfo)); + + pInfo->slotID = 1; + if (soft_token.flags.login_done) + pInfo->state = CKS_RO_USER_FUNCTIONS; + else + pInfo->state = CKS_RO_PUBLIC_SESSION; + pInfo->flags = CKF_SERIAL_SESSION; + pInfo->ulDeviceError = 0; + + return CKR_OK; +} + +CK_RV +C_Login(CK_SESSION_HANDLE hSession, + CK_USER_TYPE userType, + CK_UTF8CHAR_PTR pPin, + CK_ULONG ulPinLen) +{ + char *pin = NULL; + CK_RV ret; + INIT_CONTEXT(); + + st_logf("Login\n"); + + VERIFY_SESSION_HANDLE(hSession, NULL); + + if (pPin != NULL_PTR) { + int aret; + + aret = asprintf(&pin, "%.*s", (int)ulPinLen, pPin); + if (aret != -1 && pin) + st_logf("type: %d password: %s\n", (int)userType, pin); + else + st_logf("memory error: asprintf failed\n"); + } + + /* + * Login + */ + + ret = read_conf_file(soft_token.config_file, userType, pin); + if (ret == CKR_OK) + soft_token.flags.login_done = 1; + + free(pin); + + return soft_token.flags.login_done ? CKR_OK : CKR_PIN_INCORRECT; +} + +CK_RV +C_Logout(CK_SESSION_HANDLE hSession) +{ + st_logf("Logout\n"); + INIT_CONTEXT(); + + VERIFY_SESSION_HANDLE(hSession, NULL); + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +C_GetObjectSize(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ULONG_PTR pulSize) +{ + st_logf("GetObjectSize\n"); + INIT_CONTEXT(); + + VERIFY_SESSION_HANDLE(hSession, NULL); + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +C_GetAttributeValue(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount) +{ + struct session_state *state; + struct st_object *obj; + CK_ULONG i; + CK_RV ret; + int j; + + INIT_CONTEXT(); + + st_logf("GetAttributeValue: %lx\n", + (unsigned long)HANDLE_OBJECT_ID(hObject)); + VERIFY_SESSION_HANDLE(hSession, &state); + + if ((ret = object_handle_to_object(hObject, &obj)) != CKR_OK) { + st_logf("object not found: %lx\n", + (unsigned long)HANDLE_OBJECT_ID(hObject)); + return ret; + } + + for (i = 0; i < ulCount; i++) { + st_logf(" getting 0x%08lx\n", (unsigned long)pTemplate[i].type); + for (j = 0; j < obj->num_attributes; j++) { + if (obj->attrs[j].secret) { + pTemplate[i].ulValueLen = (CK_ULONG)-1; + break; + } + if (pTemplate[i].type == obj->attrs[j].attribute.type) { + if (pTemplate[i].pValue != NULL_PTR && obj->attrs[j].secret == 0) { + if (pTemplate[i].ulValueLen >= obj->attrs[j].attribute.ulValueLen) + memcpy(pTemplate[i].pValue, obj->attrs[j].attribute.pValue, + obj->attrs[j].attribute.ulValueLen); + } + pTemplate[i].ulValueLen = obj->attrs[j].attribute.ulValueLen; + break; + } + } + if (j == obj->num_attributes) { + st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate[i].type); + pTemplate[i].ulValueLen = (CK_ULONG)-1; + } + + } + return CKR_OK; +} + +CK_RV +C_FindObjectsInit(CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount) +{ + struct session_state *state; + + st_logf("FindObjectsInit\n"); + + INIT_CONTEXT(); + + VERIFY_SESSION_HANDLE(hSession, &state); + + if (state->find.next_object != -1) { + application_error("application didn't do C_FindObjectsFinal\n"); + find_object_final(state); + } + if (ulCount) { + CK_ULONG i; + + print_attributes(pTemplate, ulCount); + + state->find.attributes = + calloc(1, ulCount * sizeof(state->find.attributes[0])); + if (state->find.attributes == NULL) + return CKR_DEVICE_MEMORY; + for (i = 0; i < ulCount; i++) { + state->find.attributes[i].pValue = + malloc(pTemplate[i].ulValueLen); + if (state->find.attributes[i].pValue == NULL) { + find_object_final(state); + return CKR_DEVICE_MEMORY; + } + memcpy(state->find.attributes[i].pValue, + pTemplate[i].pValue, pTemplate[i].ulValueLen); + state->find.attributes[i].type = pTemplate[i].type; + state->find.attributes[i].ulValueLen = pTemplate[i].ulValueLen; + } + state->find.num_attributes = ulCount; + state->find.next_object = 0; + } else { + st_logf("find all objects\n"); + state->find.attributes = NULL; + state->find.num_attributes = 0; + state->find.next_object = 0; + } + + return CKR_OK; +} + +CK_RV +C_FindObjects(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE_PTR phObject, + CK_ULONG ulMaxObjectCount, + CK_ULONG_PTR pulObjectCount) +{ + struct session_state *state; + int i; + + INIT_CONTEXT(); + + st_logf("FindObjects\n"); + + VERIFY_SESSION_HANDLE(hSession, &state); + + if (state->find.next_object == -1) { + application_error("application didn't do C_FindObjectsInit\n"); + return CKR_ARGUMENTS_BAD; + } + if (ulMaxObjectCount == 0) { + application_error("application asked for 0 objects\n"); + return CKR_ARGUMENTS_BAD; + } + *pulObjectCount = 0; + for (i = state->find.next_object; i < soft_token.object.num_objs; i++) { + st_logf("FindObjects: %d\n", i); + state->find.next_object = i + 1; + if (attributes_match(soft_token.object.objs[i], + state->find.attributes, + state->find.num_attributes)) { + *phObject++ = soft_token.object.objs[i]->object_handle; + ulMaxObjectCount--; + (*pulObjectCount)++; + if (ulMaxObjectCount == 0) + break; + } + } + return CKR_OK; +} + +CK_RV +C_FindObjectsFinal(CK_SESSION_HANDLE hSession) +{ + struct session_state *state; + + INIT_CONTEXT(); + + st_logf("FindObjectsFinal\n"); + VERIFY_SESSION_HANDLE(hSession, &state); + find_object_final(state); + return CKR_OK; +} + +static CK_RV +commonInit(CK_ATTRIBUTE *attr_match, int attr_match_len, + const CK_MECHANISM_TYPE *mechs, int mechs_len, + const CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey, + struct st_object **o) +{ + CK_RV ret; + int i; + + *o = NULL; + if ((ret = object_handle_to_object(hKey, o)) != CKR_OK) + return ret; + + ret = attributes_match(*o, attr_match, attr_match_len); + if (!ret) { + application_error("called commonInit on key that doesn't " + "support required attr"); + return CKR_ARGUMENTS_BAD; + } + + for (i = 0; i < mechs_len; i++) + if (mechs[i] == pMechanism->mechanism) + break; + if (i == mechs_len) { + application_error("called mech (%08lx) not supported\n", + pMechanism->mechanism); + return CKR_ARGUMENTS_BAD; + } + return CKR_OK; +} + + +static CK_RV +dup_mechanism(CK_MECHANISM_PTR *dp, const CK_MECHANISM_PTR pMechanism) +{ + CK_MECHANISM_PTR p; + + p = malloc(sizeof(*p)); + if (p == NULL) + return CKR_DEVICE_MEMORY; + + if (*dp) + free(*dp); + *dp = p; + memcpy(p, pMechanism, sizeof(*p)); + + return CKR_OK; +} + +CK_RV +C_DigestInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism) +{ + st_logf("DigestInit\n"); + INIT_CONTEXT(); + VERIFY_SESSION_HANDLE(hSession, NULL); + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +C_SignInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey) +{ + struct session_state *state; + CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS }; + CK_BBOOL bool_true = CK_TRUE; + CK_ATTRIBUTE attr[] = { + { CKA_SIGN, &bool_true, sizeof(bool_true) } + }; + struct st_object *o; + CK_RV ret; + + INIT_CONTEXT(); + st_logf("SignInit\n"); + VERIFY_SESSION_HANDLE(hSession, &state); + + ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]), + mechs, sizeof(mechs)/sizeof(mechs[0]), + pMechanism, hKey, &o); + if (ret) + return ret; + + ret = dup_mechanism(&state->sign_mechanism, pMechanism); + if (ret == CKR_OK) + state->sign_object = OBJECT_ID(o); + + return CKR_OK; +} + +CK_RV +C_Sign(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen) +{ + struct session_state *state; + struct st_object *o; + CK_RV ret; + int hret; + const AlgorithmIdentifier *alg; + heim_octet_string sig, data; + + INIT_CONTEXT(); + st_logf("Sign\n"); + VERIFY_SESSION_HANDLE(hSession, &state); + + sig.data = NULL; + sig.length = 0; + + if (state->sign_object == -1) + return CKR_ARGUMENTS_BAD; + + if (pulSignatureLen == NULL) { + st_logf("signature len NULL\n"); + ret = CKR_ARGUMENTS_BAD; + goto out; + } + + if (pData == NULL_PTR) { + st_logf("data NULL\n"); + ret = CKR_ARGUMENTS_BAD; + goto out; + } + + o = soft_token.object.objs[state->sign_object]; + + if (hx509_cert_have_private_key(o->cert) == 0) { + st_logf("private key NULL\n"); + return CKR_ARGUMENTS_BAD; + } + + switch(state->sign_mechanism->mechanism) { + case CKM_RSA_PKCS: + alg = hx509_signature_rsa_pkcs1_x509(); + break; + default: + ret = CKR_FUNCTION_NOT_SUPPORTED; + goto out; + } + + data.data = pData; + data.length = ulDataLen; + + hret = _hx509_create_signature(context, + _hx509_cert_private_key(o->cert), + alg, + &data, + NULL, + &sig); + if (hret) { + ret = CKR_DEVICE_ERROR; + goto out; + } + *pulSignatureLen = sig.length; + + if (pSignature != NULL_PTR) + memcpy(pSignature, sig.data, sig.length); + + ret = CKR_OK; + out: + if (sig.data) { + memset(sig.data, 0, sig.length); + der_free_octet_string(&sig); + } + return ret; +} + +CK_RV +C_SignUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen) +{ + INIT_CONTEXT(); + st_logf("SignUpdate\n"); + VERIFY_SESSION_HANDLE(hSession, NULL); + return CKR_FUNCTION_NOT_SUPPORTED; +} + + +CK_RV +C_SignFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen) +{ + INIT_CONTEXT(); + st_logf("SignUpdate\n"); + VERIFY_SESSION_HANDLE(hSession, NULL); + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +C_VerifyInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey) +{ + struct session_state *state; + CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS }; + CK_BBOOL bool_true = CK_TRUE; + CK_ATTRIBUTE attr[] = { + { CKA_VERIFY, &bool_true, sizeof(bool_true) } + }; + struct st_object *o; + CK_RV ret; + + INIT_CONTEXT(); + st_logf("VerifyInit\n"); + VERIFY_SESSION_HANDLE(hSession, &state); + + ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]), + mechs, sizeof(mechs)/sizeof(mechs[0]), + pMechanism, hKey, &o); + if (ret) + return ret; + + ret = dup_mechanism(&state->verify_mechanism, pMechanism); + if (ret == CKR_OK) + state->verify_object = OBJECT_ID(o); + + return ret; +} + +CK_RV +C_Verify(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, + CK_ULONG ulSignatureLen) +{ + struct session_state *state; + struct st_object *o; + const AlgorithmIdentifier *alg; + CK_RV ret; + int hret; + heim_octet_string data, sig; + + INIT_CONTEXT(); + st_logf("Verify\n"); + VERIFY_SESSION_HANDLE(hSession, &state); + + if (state->verify_object == -1) + return CKR_ARGUMENTS_BAD; + + o = soft_token.object.objs[state->verify_object]; + + switch(state->verify_mechanism->mechanism) { + case CKM_RSA_PKCS: + alg = hx509_signature_rsa_pkcs1_x509(); + break; + default: + ret = CKR_FUNCTION_NOT_SUPPORTED; + goto out; + } + + sig.data = pData; + sig.length = ulDataLen; + data.data = pSignature; + data.length = ulSignatureLen; + + hret = _hx509_verify_signature(context, + o->cert, + alg, + &data, + &sig); + if (hret) { + ret = CKR_GENERAL_ERROR; + goto out; + } + ret = CKR_OK; + + out: + return ret; +} + + +CK_RV +C_VerifyUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen) +{ + INIT_CONTEXT(); + st_logf("VerifyUpdate\n"); + VERIFY_SESSION_HANDLE(hSession, NULL); + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +C_VerifyFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, + CK_ULONG ulSignatureLen) +{ + INIT_CONTEXT(); + st_logf("VerifyFinal\n"); + VERIFY_SESSION_HANDLE(hSession, NULL); + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +C_GenerateRandom(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR RandomData, + CK_ULONG ulRandomLen) +{ + INIT_CONTEXT(); + st_logf("GenerateRandom\n"); + VERIFY_SESSION_HANDLE(hSession, NULL); + return CKR_FUNCTION_NOT_SUPPORTED; +} + + +CK_FUNCTION_LIST funcs = { + { 2, 11 }, + C_Initialize, + C_Finalize, + C_GetInfo, + C_GetFunctionList, + C_GetSlotList, + C_GetSlotInfo, + C_GetTokenInfo, + C_GetMechanismList, + C_GetMechanismInfo, + C_InitToken, + (void *)func_not_supported, /* C_InitPIN */ + (void *)func_not_supported, /* C_SetPIN */ + C_OpenSession, + C_CloseSession, + C_CloseAllSessions, + C_GetSessionInfo, + (void *)func_not_supported, /* C_GetOperationState */ + (void *)func_not_supported, /* C_SetOperationState */ + C_Login, + C_Logout, + (void *)func_not_supported, /* C_CreateObject */ + (void *)func_not_supported, /* C_CopyObject */ + (void *)func_not_supported, /* C_DestroyObject */ + (void *)func_not_supported, /* C_GetObjectSize */ + C_GetAttributeValue, + (void *)func_not_supported, /* C_SetAttributeValue */ + C_FindObjectsInit, + C_FindObjects, + C_FindObjectsFinal, + (void *)func_not_supported, /* C_EncryptInit, */ + (void *)func_not_supported, /* C_Encrypt, */ + (void *)func_not_supported, /* C_EncryptUpdate, */ + (void *)func_not_supported, /* C_EncryptFinal, */ + (void *)func_not_supported, /* C_DecryptInit, */ + (void *)func_not_supported, /* C_Decrypt, */ + (void *)func_not_supported, /* C_DecryptUpdate, */ + (void *)func_not_supported, /* C_DecryptFinal, */ + C_DigestInit, + (void *)func_not_supported, /* C_Digest */ + (void *)func_not_supported, /* C_DigestUpdate */ + (void *)func_not_supported, /* C_DigestKey */ + (void *)func_not_supported, /* C_DigestFinal */ + C_SignInit, + C_Sign, + C_SignUpdate, + C_SignFinal, + (void *)func_not_supported, /* C_SignRecoverInit */ + (void *)func_not_supported, /* C_SignRecover */ + C_VerifyInit, + C_Verify, + C_VerifyUpdate, + C_VerifyFinal, + (void *)func_not_supported, /* C_VerifyRecoverInit */ + (void *)func_not_supported, /* C_VerifyRecover */ + (void *)func_not_supported, /* C_DigestEncryptUpdate */ + (void *)func_not_supported, /* C_DecryptDigestUpdate */ + (void *)func_not_supported, /* C_SignEncryptUpdate */ + (void *)func_not_supported, /* C_DecryptVerifyUpdate */ + (void *)func_not_supported, /* C_GenerateKey */ + (void *)func_not_supported, /* C_GenerateKeyPair */ + (void *)func_not_supported, /* C_WrapKey */ + (void *)func_not_supported, /* C_UnwrapKey */ + (void *)func_not_supported, /* C_DeriveKey */ + (void *)func_not_supported, /* C_SeedRandom */ + C_GenerateRandom, + (void *)func_not_supported, /* C_GetFunctionStatus */ + (void *)func_not_supported, /* C_CancelFunction */ + (void *)func_not_supported /* C_WaitForSlotEvent */ +}; diff --git a/third_party/heimdal/lib/hx509/test_ca.in b/third_party/heimdal/lib/hx509/test_ca.in new file mode 100644 index 0000000..cf739a1 --- /dev/null +++ b/third_party/heimdal/lib/hx509/test_ca.in @@ -0,0 +1,480 @@ +#!/bin/sh +# +# Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan +# (Royal Institute of Technology, Stockholm, Sweden). +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Institute nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $Id$ +# + +srcdir="@srcdir@" +objdir="@objdir@" + +stat="--statistic-file=${objdir}/statfile" + +hxtool="${TESTS_ENVIRONMENT} ./hxtool ${stat}" + +if ${hxtool} info | grep 'rsa: hcrypto null RSA' > /dev/null ; then + exit 77 +fi +if ${hxtool} info | grep 'rand: not available' > /dev/null ; then + exit 77 +fi + +echo "create certificate request" +${hxtool} request-create \ + --subject="CN=Love,DC=it,DC=su,DC=se" \ + --key=FILE:$srcdir/data/key.der \ + pkcs10-request.der || exit 1 + +echo "issue certificate" +${hxtool} issue-certificate \ + --ca-certificate=FILE:$srcdir/data/ca.crt,$srcdir/data/ca.key \ + --subject="cn=foo" \ + --req="PKCS10:pkcs10-request.der" \ + --certificate="FILE:cert-ee.pem" || exit 1 + +echo "verify certificate" +${hxtool} verify --missing-revoke \ + cert:FILE:cert-ee.pem \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null || exit 1 + +echo "issue crl (no cert)" +${hxtool} crl-sign \ + --crl-file=crl.crl \ + --signer=FILE:$srcdir/data/ca.crt,$srcdir/data/ca.key || exit 1 + +echo "verify certificate (with CRL)" +${hxtool} verify \ + cert:FILE:cert-ee.pem \ + crl:FILE:crl.crl \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null || exit 1 + +echo "issue crl (with cert)" +${hxtool} crl-sign \ + --crl-file=crl.crl \ + --signer=FILE:$srcdir/data/ca.crt,$srcdir/data/ca.key \ + FILE:cert-ee.pem || exit 1 + +echo "verify certificate (included in CRL)" +${hxtool} verify \ + cert:FILE:cert-ee.pem \ + crl:FILE:crl.crl \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null && exit 1 + +# XXX Check that the certs issued below have the requested content + +echo "issue crl (with cert)" +${hxtool} crl-sign \ + --crl-file=crl.crl \ + --lifetime='1 month' \ + --signer=FILE:$srcdir/data/ca.crt,$srcdir/data/ca.key \ + FILE:cert-ee.pem || exit 1 + +echo "verify certificate (included in CRL, and lifetime 1 month)" +${hxtool} verify \ + cert:FILE:cert-ee.pem \ + crl:FILE:crl.crl \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null && exit 1 + +echo "issue certificate (10years 1 month)" +${hxtool} issue-certificate \ + --ca-certificate=FILE:$srcdir/data/ca.crt,$srcdir/data/ca.key \ + --subject="cn=foo" \ + --lifetime="10years 1 month" \ + --req="PKCS10:pkcs10-request.der" \ + --permanent-id=1.2.3.4.5.6.6:SomeVendor:A0B1C2D3 \ + --hardware-module-name=tcg-tpm20:SomeVendor:Z0Y1X2W3 \ + --policy="1.2.3.4.5.6:data:foo this is a warning" \ + --policy="id-x509-ce-certificatePolicies-anyPolicy" \ + --policy-mapping="1.2.3.4.5.6:1.2.3.4.5.6" \ + --policy-mapping="1.2.3.4.5.6:1.2.3.4.5.7" \ + --certificate="FILE:cert-ee.pem" || exit 1 +${hxtool} print --content FILE:cert-ee.pem || exit 1 + +echo "issue certificate (with https ekus)" +${hxtool} issue-certificate \ + --ca-certificate=FILE:$srcdir/data/ca.crt,$srcdir/data/ca.key \ + --subject="cn=foo" \ + --type="https-server" \ + --type="https-client" \ + --req="PKCS10:pkcs10-request.der" \ + --certificate="FILE:cert-ee.pem" || exit 1 +${hxtool} print --content FILE:cert-ee.pem || exit 1 + +echo "issue certificate (pkinit KDC)" +${hxtool} issue-certificate \ + --ca-certificate=FILE:$srcdir/data/ca.crt,$srcdir/data/ca.key \ + --subject="cn=foo" \ + --type="pkinit-kdc" \ + --pk-init-principal="krbtgt/TEST.H5L.SE@TEST.H5L.SE" \ + --req="PKCS10:pkcs10-request.der" \ + --certificate="FILE:cert-ee.pem" || exit 1 +${hxtool} print --content FILE:cert-ee.pem || exit 1 + +echo "issue certificate (pkinit client)" +${hxtool} issue-certificate \ + --ca-certificate=FILE:$srcdir/data/ca.crt,$srcdir/data/ca.key \ + --subject="cn=foo" \ + --type="pkinit-client" \ + --pk-init-principal="lha@TEST.H5L.SE" \ + --req="PKCS10:pkcs10-request.der" \ + --certificate="FILE:cert-ee.pem" || exit 1 +${hxtool} print --content FILE:cert-ee.pem || exit 1 + +echo "issue certificate (hostnames)" +${hxtool} issue-certificate \ + --ca-certificate=FILE:$srcdir/data/ca.crt,$srcdir/data/ca.key \ + --subject="cn=foo" \ + --type="https-server" \ + --hostname="www.test.h5l.se" \ + --hostname="ftp.test.h5l.se" \ + --req="PKCS10:pkcs10-request.der" \ + --certificate="FILE:cert-ee.pem" || exit 1 +${hxtool} print --content FILE:cert-ee.pem || exit 1 + +echo "verify certificate hostname (ok)" +${hxtool} verify --missing-revoke \ + --hostname=www.test.h5l.se \ + cert:FILE:cert-ee.pem \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null || exit 1 + +echo "verify certificate hostname (fail)" +${hxtool} verify --missing-revoke \ + --hostname=www2.test.h5l.se \ + cert:FILE:cert-ee.pem \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null && exit 1 + +echo "verify certificate hostname (fail)" +${hxtool} verify --missing-revoke \ + --hostname=2www.test.h5l.se \ + cert:FILE:cert-ee.pem \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null && exit 1 + +echo "issue certificate (hostname in CN)" +${hxtool} issue-certificate \ + --ca-certificate=FILE:$srcdir/data/ca.crt,$srcdir/data/ca.key \ + --subject="cn=www.test.h5l.se" \ + --type="https-server" \ + --req="PKCS10:pkcs10-request.der" \ + --certificate="FILE:cert-ee.pem" || exit 1 +${hxtool} print --content FILE:cert-ee.pem || exit 1 + +echo "verify certificate hostname (ok)" +${hxtool} verify --missing-revoke \ + --hostname=www.test.h5l.se \ + cert:FILE:cert-ee.pem \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null || exit 1 + +echo "verify certificate hostname (fail)" +${hxtool} verify --missing-revoke \ + --hostname=www2.test.h5l.se \ + cert:FILE:cert-ee.pem \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null && exit 1 + +echo "issue certificate (email)" +${hxtool} issue-certificate \ + --ca-certificate=FILE:$srcdir/data/ca.crt,$srcdir/data/ca.key \ + --subject="cn=foo" \ + --email="lha@test.h5l.se" \ + --email="test@test.h5l.se" \ + --req="PKCS10:pkcs10-request.der" \ + --certificate="FILE:cert-ee.pem" || exit 1 +${hxtool} print --content FILE:cert-ee.pem || exit 1 + +echo "issue certificate (email, null subject DN)" +${hxtool} issue-certificate \ + --ca-certificate=FILE:$srcdir/data/ca.crt,$srcdir/data/ca.key \ + --subject="" \ + --email="lha@test.h5l.se" \ + --req="PKCS10:pkcs10-request.der" \ + --certificate="FILE:cert-null.pem" || exit 1 +${hxtool} print --content FILE:cert-null.pem || exit 1 + +echo "issue certificate (jabber)" +${hxtool} issue-certificate \ + --ca-certificate=FILE:$srcdir/data/ca.crt,$srcdir/data/ca.key \ + --subject="cn=foo" \ + --jid="lha@test.h5l.se" \ + --req="PKCS10:pkcs10-request.der" \ + --certificate="FILE:cert-ee.pem" || exit 1 +${hxtool} print --content FILE:cert-ee.pem || exit 1 + +echo "issue self-signed cert" +${hxtool} issue-certificate \ + --self-signed \ + --ca-private-key=FILE:$srcdir/data/key.der \ + --subject="cn=test" \ + --certificate="FILE:cert-ee.pem" || exit 1 +${hxtool} print --content FILE:cert-ee.pem || exit 1 + +echo "issue ca cert" +${hxtool} issue-certificate \ + --ca-certificate=FILE:$srcdir/data/ca.crt,$srcdir/data/ca.key \ + --issue-ca \ + --subject="cn=ca-cert" \ + --req="PKCS10:pkcs10-request.der" \ + --certificate="FILE:cert-ca.der" || exit 1 +${hxtool} print --content FILE:cert-ca.der || exit 1 + +echo "issue self-signed ca cert" +${hxtool} issue-certificate \ + --self-signed \ + --issue-ca \ + --ca-private-key=FILE:$srcdir/data/key.der \ + --subject="cn=ca-root" \ + --certificate="FILE:cert-ca.der" || exit 1 +${hxtool} print --content FILE:cert-ca.der || exit 1 + +echo "issue proxy certificate" +${hxtool} issue-certificate \ + --ca-certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ + --issue-proxy \ + --req="PKCS10:pkcs10-request.der" \ + --certificate="FILE:cert-proxy.der" || exit 1 +${hxtool} print --content FILE:cert-proxy.der || exit 1 + +echo "verify proxy cert" +${hxtool} verify --missing-revoke \ + --allow-proxy-certificate \ + cert:FILE:cert-proxy.der \ + chain:FILE:$srcdir/data/test.crt \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null || exit 1 + +echo "issue ca cert (generate rsa key)" +${hxtool} issue-certificate \ + --self-signed \ + --issue-ca \ + --serial-number="deadbeaf" \ + --generate-key=rsa \ + --path-length=-1 \ + --subject="cn=ca2-cert" \ + --certificate="FILE:cert-ca.pem" || exit 1 +${hxtool} print --content FILE:cert-ca.pem || exit 1 + +echo "issue sub-ca cert (generate rsa key)" +${hxtool} issue-certificate \ + --ca-certificate=FILE:cert-ca.pem \ + --issue-ca \ + --serial-number="deadbeaf22" \ + --generate-key=rsa \ + --subject="cn=sub-ca2-cert" \ + --certificate="FILE:cert-sub-ca.pem" || exit 1 +${hxtool} print --content FILE:cert-sub-ca.pem || exit 1 + +echo "issue ee cert (generate rsa key)" +${hxtool} issue-certificate \ + --ca-certificate=FILE:cert-ca.pem \ + --generate-key=rsa \ + --subject="cn=cert-ee2" \ + --certificate="FILE:cert-ee.pem" || exit 1 +${hxtool} print --content FILE:cert-ee.pem || exit 1 + +echo "issue sub-ca ee cert (generate rsa key)" +${hxtool} issue-certificate \ + --ca-certificate=FILE:cert-sub-ca.pem \ + --generate-key=rsa \ + --subject="cn=cert-sub-ee2" \ + --certificate="FILE:cert-sub-ee.pem" || exit 1 +${hxtool} print --content FILE:cert-sub-ee.pem || exit 1 + +echo "verify certificate (ee)" +${hxtool} verify --missing-revoke \ + cert:FILE:cert-ee.pem \ + anchor:FILE:cert-ca.pem > /dev/null || exit 1 + +echo "verify certificate (sub-ee)" +${hxtool} verify --missing-revoke \ + cert:FILE:cert-sub-ee.pem \ + chain:FILE:cert-sub-ca.pem \ + anchor:FILE:cert-ca.pem || exit 1 + +echo "sign CMS signature (generate key)" +${hxtool} cms-create-sd \ + --certificate=FILE:cert-ee.pem \ + "$srcdir/test_name.c" \ + sd.data > /dev/null || exit 1 + +echo "verify CMS signature (generate key)" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:cert-ca.pem \ + sd.data sd.data.out > /dev/null || exit 1 +cmp "$srcdir/test_name.c" sd.data.out || exit 1 + +echo "extend ca cert" +${hxtool} issue-certificate \ + --self-signed \ + --issue-ca \ + --lifetime="2years" \ + --serial-number="deadbeaf" \ + --ca-private-key=FILE:cert-ca.pem \ + --subject="cn=ca2-cert" \ + --certificate="FILE:cert-ca.pem" || exit 1 +${hxtool} print --content FILE:cert-ca.pem || exit 1 + +echo "verify certificate generated by previous ca" +${hxtool} verify --missing-revoke \ + cert:FILE:cert-ee.pem \ + anchor:FILE:cert-ca.pem > /dev/null || exit 1 + +echo "extend ca cert (template)" +${hxtool} issue-certificate \ + --self-signed \ + --issue-ca \ + --lifetime="3years" \ + --template-certificate="FILE:cert-ca.pem" \ + --template-fields="serialNumber,notBefore,subject" \ + --path-length=-1 \ + --ca-private-key=FILE:cert-ca.pem \ + --certificate="FILE:cert-ca.pem" || exit 1 +${hxtool} print --content FILE:cert-ca.pem || exit 1 + +echo "verify certificate generated by previous ca" +${hxtool} verify --missing-revoke \ + cert:FILE:cert-ee.pem \ + anchor:FILE:cert-ca.pem > /dev/null || exit 1 + +echo "extend sub-ca cert (template)" +${hxtool} issue-certificate \ + --ca-certificate=FILE:cert-ca.pem \ + --issue-ca \ + --lifetime="2years" \ + --template-certificate="FILE:cert-sub-ca.pem" \ + --template-fields="serialNumber,notBefore,subject,SPKI" \ + --certificate="FILE:cert-sub-ca2.pem" || exit 1 +${hxtool} print --content FILE:cert-sub-ca2.pem || exit 1 + +echo "verify certificate (sub-ee) with extended chain" +${hxtool} verify --missing-revoke \ + cert:FILE:cert-sub-ee.pem \ + chain:FILE:cert-sub-ca.pem \ + anchor:FILE:cert-ca.pem > /dev/null || exit 1 + +echo "+++++++++++ test basic constraints" + +echo "extend ca cert (too low path-length constraint)" +${hxtool} issue-certificate \ + --self-signed \ + --issue-ca \ + --lifetime="3years" \ + --template-certificate="FILE:cert-ca.pem" \ + --template-fields="serialNumber,notBefore,subject" \ + --path-length=0 \ + --ca-private-key=FILE:cert-ca.pem \ + --certificate="FILE:cert-ca.pem" || exit 1 + +echo "verify failure of certificate (sub-ee) with path-length constraint" +${hxtool} verify --missing-revoke \ + cert:FILE:cert-sub-ee.pem \ + chain:FILE:cert-sub-ca.pem \ + anchor:FILE:cert-ca.pem > /dev/null && exit 1 + +echo "extend ca cert (exact path-length constraint)" +${hxtool} issue-certificate \ + --self-signed \ + --issue-ca \ + --lifetime="3years" \ + --template-certificate="FILE:cert-ca.pem" \ + --template-fields="serialNumber,notBefore,subject" \ + --path-length=1 \ + --ca-private-key=FILE:cert-ca.pem \ + --certificate="FILE:cert-ca.pem" || exit 1 + +echo "verify certificate (sub-ee) with exact path-length constraint" +${hxtool} verify --missing-revoke \ + cert:FILE:cert-sub-ee.pem \ + chain:FILE:cert-sub-ca.pem \ + anchor:FILE:cert-ca.pem > /dev/null || exit 1 + +echo "Check missing basicConstrants.isCa" +${hxtool} issue-certificate \ + --ca-certificate=FILE:cert-ca.pem \ + --lifetime="2years" \ + --template-certificate="FILE:cert-sub-ca.pem" \ + --template-fields="serialNumber,notBefore,subject,SPKI" \ + --certificate="FILE:cert-sub-ca2.pem" || exit 1 + +echo "verify failure certificate (sub-ee) with missing isCA" +${hxtool} verify --missing-revoke \ + cert:FILE:cert-sub-ee.pem \ + chain:FILE:cert-sub-ca2.pem \ + anchor:FILE:cert-ca.pem > /dev/null && exit 1 + +echo "issue ee cert (crl uri)" +${hxtool} issue-certificate \ + --ca-certificate=FILE:cert-ca.pem \ + --req="PKCS10:pkcs10-request.der" \ + --crl-uri="http://www.test.h5l.se/crl1.crl" \ + --subject="cn=cert-ee-crl-uri" \ + --certificate="FILE:cert-ee.pem" || exit 1 + +echo "issue null subject cert" +${hxtool} issue-certificate \ + --ca-certificate=FILE:cert-ca.pem \ + --req="PKCS10:pkcs10-request.der" \ + --subject="" \ + --email="lha@test.h5l.se" \ + --certificate="FILE:cert-ee.pem" || exit 1 + +echo "verify certificate null subject" +${hxtool} verify --missing-revoke \ + cert:FILE:cert-ee.pem \ + anchor:FILE:cert-ca.pem > /dev/null || exit 1 + +echo "+++++++++++ test sigalg" + +echo "issue cert with sha256" +${hxtool} issue-certificate \ + --ca-certificate=FILE:cert-ca.pem \ + --signature-algorithm=rsa-with-sha256 \ + --subject="cn=foo" \ + --req="PKCS10:pkcs10-request.der" \ + --certificate="FILE:cert-ee.pem" || exit 1 + +echo "verify certificate" +${hxtool} verify --missing-revoke \ + cert:FILE:cert-ee.pem \ + anchor:FILE:cert-ca.pem > /dev/null || exit 1 + +echo "issue cert with sha1" +${hxtool} issue-certificate \ + --ca-certificate=FILE:cert-ca.pem \ + --signature-algorithm=rsa-with-sha1 \ + --subject="cn=foo" \ + --req="PKCS10:pkcs10-request.der" \ + --certificate="FILE:cert-ee.pem" || exit 1 + +echo "verify certificate" +${hxtool} verify --missing-revoke \ + cert:FILE:cert-ee.pem \ + anchor:FILE:cert-ca.pem > /dev/null || exit 1 + +exit 0 diff --git a/third_party/heimdal/lib/hx509/test_cert.in b/third_party/heimdal/lib/hx509/test_cert.in new file mode 100644 index 0000000..5fa14d0 --- /dev/null +++ b/third_party/heimdal/lib/hx509/test_cert.in @@ -0,0 +1,84 @@ +#!/bin/sh +# +# Copyright (c) 2007 Kungliga Tekniska Högskolan +# (Royal Institute of Technology, Stockholm, Sweden). +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Institute nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $Id: test_chain.in 20809 2007-06-03 03:19:06Z lha $ +# + +srcdir="@srcdir@" +objdir="@objdir@" + +hxtool="${TESTS_ENVIRONMENT} ./hxtool ${stat}" +if ${hxtool} info | grep 'rsa: hcrypto null RSA' > /dev/null ; then + exit 77 +fi +if ${hxtool} info | grep 'rand: not available' > /dev/null ; then + exit 77 +fi + +echo "print DIR" +${hxtool} print --content DIR:$srcdir/data > /dev/null 2>/dev/null || exit 1 + +echo "print FILE" +for a in $srcdir/data/*.crt; do + ${hxtool} print --content FILE:"$a" > /dev/null 2>/dev/null +done + +echo "print NULL" +${hxtool} print --content NULL: > /dev/null || exit 1 + +echo "copy dance" +${hxtool} certificate-copy \ + FILE:${srcdir}/data/test.crt PEM-FILE:cert-pem.tmp || exit 1 + +${hxtool} certificate-copy PEM-FILE:cert-pem.tmp DER-FILE:cert-der.tmp || exit 1 +${hxtool} certificate-copy DER-FILE:cert-der.tmp PEM-FILE:cert-pem2.tmp || exit 1 + +cmp cert-pem.tmp cert-pem2.tmp || exit 1 + +echo "verify n0ll cert (fail)" +${hxtool} verify --missing-revoke \ + --hostname=foo.com \ + cert:FILE:$srcdir/data/n0ll.pem \ + anchor:FILE:$srcdir/data/n0ll.pem && exit 1 + +echo "verify n0ll cert (fail)" +${hxtool} verify --missing-revoke \ + cert:FILE:$srcdir/data/n0ll.pem \ + anchor:FILE:$srcdir/data/n0ll.pem && exit 1 + +echo "check that windows cert with utf16 in printable string works" +${hxtool} verify --missing-revoke \ + cert:FILE:$srcdir/data/win-u16-in-printablestring.der \ + anchor:FILE:$srcdir/data/win-u16-in-printablestring.der || exit 1 + +exit 0 diff --git a/third_party/heimdal/lib/hx509/test_chain.in b/third_party/heimdal/lib/hx509/test_chain.in new file mode 100644 index 0000000..b8c8cf5 --- /dev/null +++ b/third_party/heimdal/lib/hx509/test_chain.in @@ -0,0 +1,256 @@ +#!/bin/sh +# +# Copyright (c) 2004 - 2006 Kungliga Tekniska Högskolan +# (Royal Institute of Technology, Stockholm, Sweden). +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Institute nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $Id$ +# + +srcdir="@srcdir@" +objdir="@objdir@" + +stat="--statistic-file=${objdir}/statfile" + +hxtool="${TESTS_ENVIRONMENT} ./hxtool ${stat}" +if ${hxtool} info | grep 'rsa: hcrypto null RSA' > /dev/null ; then + exit 77 +fi +if ${hxtool} info | grep 'rand: not available' > /dev/null ; then + exit 77 +fi + +echo "cert -> root" +${hxtool} verify --missing-revoke \ + cert:FILE:$srcdir/data/test.crt \ + chain:FILE:$srcdir/data/test.crt \ + chain:FILE:$srcdir/data/ca.crt \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null || exit 1 + +echo "cert -> root" +${hxtool} verify --missing-revoke \ + cert:FILE:$srcdir/data/test.crt \ + chain:FILE:$srcdir/data/ca.crt \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null || exit 1 + +echo "cert -> root" +${hxtool} verify --missing-revoke \ + cert:FILE:$srcdir/data/test.crt \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null || exit 1 + +echo "sub-cert -> root" +${hxtool} verify --missing-revoke \ + cert:FILE:$srcdir/data/sub-cert.crt \ + chain:FILE:$srcdir/data/ca.crt \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null && exit 1 + +echo "sub-cert -> sub-ca -> root" +${hxtool} verify --missing-revoke \ + cert:FILE:$srcdir/data/sub-cert.crt \ + chain:FILE:$srcdir/data/sub-ca.crt \ + chain:FILE:$srcdir/data/ca.crt \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null || exit 1 + +echo "sub-cert -> sub-ca" +${hxtool} verify --missing-revoke \ + cert:FILE:$srcdir/data/sub-cert.crt \ + anchor:FILE:$srcdir/data/sub-ca.crt > /dev/null || exit 1 + +echo "sub-cert -> sub-ca -> root" +${hxtool} verify --missing-revoke \ + cert:FILE:$srcdir/data/sub-cert.crt \ + chain:FILE:$srcdir/data/sub-ca.crt \ + chain:FILE:$srcdir/data/ca.crt \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null || exit 1 + +echo "sub-cert -> sub-ca -> root" +${hxtool} verify --missing-revoke \ + cert:FILE:$srcdir/data/sub-cert.crt \ + chain:FILE:$srcdir/data/ca.crt \ + chain:FILE:$srcdir/data/sub-ca.crt \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null || exit 1 + +echo "sub-cert -> sub-ca -> root" +${hxtool} verify --missing-revoke \ + cert:FILE:$srcdir/data/sub-cert.crt \ + chain:FILE:$srcdir/data/sub-ca.crt \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null || exit 1 + +echo "max depth 2 (ok)" +${hxtool} verify --missing-revoke \ + --max-depth=2 \ + cert:FILE:$srcdir/data/sub-cert.crt \ + chain:FILE:$srcdir/data/sub-ca.crt \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null && exit 1 + +echo "max depth 1 (fail)" +${hxtool} verify --missing-revoke \ + --max-depth=1 \ + cert:FILE:$srcdir/data/sub-cert.crt \ + chain:FILE:$srcdir/data/sub-ca.crt \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null && exit 1 + +echo "ocsp non-ca responder" +${hxtool} verify \ + cert:FILE:$srcdir/data/test.crt \ + anchor:FILE:$srcdir/data/ca.crt \ + ocsp:FILE:$srcdir/data/ocsp-resp1-ocsp.der > /dev/null || exit 1 + +echo "ocsp ca responder" +${hxtool} verify \ + cert:FILE:$srcdir/data/test.crt \ + anchor:FILE:$srcdir/data/ca.crt \ + ocsp:FILE:$srcdir/data/ocsp-resp1-ca.der > /dev/null || exit 1 + +echo "ocsp no-ca responder, missing cert" +${hxtool} verify \ + cert:FILE:$srcdir/data/test.crt \ + anchor:FILE:$srcdir/data/ca.crt \ + ocsp:FILE:$srcdir/data/ocsp-resp1-ocsp-no-cert.der > /dev/null && exit 1 + +echo "ocsp no-ca responder, missing cert, in pool" +${hxtool} verify \ + cert:FILE:$srcdir/data/test.crt \ + anchor:FILE:$srcdir/data/ca.crt \ + ocsp:FILE:$srcdir/data/ocsp-resp1-ocsp-no-cert.der \ + chain:FILE:$srcdir/data/ocsp-responder.crt > /dev/null || exit 1 + +echo "ocsp no-ca responder, keyHash" +${hxtool} verify \ + cert:FILE:$srcdir/data/test.crt \ + anchor:FILE:$srcdir/data/ca.crt \ + ocsp:FILE:$srcdir/data/ocsp-resp1-keyhash.der > /dev/null || exit 1 + +echo "ocsp revoked cert" +${hxtool} verify \ + cert:FILE:$srcdir/data/revoke.crt \ + anchor:FILE:$srcdir/data/ca.crt \ + ocsp:FILE:$srcdir/data/ocsp-resp2.der > /dev/null && exit 1 + +for a in resp1-ocsp-no-cert resp1-ca resp1-keyhash resp2 ; do + echo "ocsp print reply $a" + ${hxtool} ocsp-print \ + $srcdir/data/ocsp-${a}.der > /dev/null || exit 1 +done + +echo "ocsp verify exists" +${hxtool} ocsp-verify \ + --ocsp-file=$srcdir/data/ocsp-resp1-ca.der \ + FILE:$srcdir/data/test.crt > /dev/null || exit 1 + +echo "ocsp verify not exists" +${hxtool} ocsp-verify \ + --ocsp-file=$srcdir/data/ocsp-resp1.der \ + FILE:$srcdir/data/ca.crt > /dev/null && exit 1 + +echo "ocsp verify revoked" +${hxtool} ocsp-verify \ + --ocsp-file=$srcdir/data/ocsp-resp2.der \ + FILE:$srcdir/data/revoke.crt > /dev/null && exit 1 + +echo "crl non-revoked cert" +${hxtool} verify \ + cert:FILE:$srcdir/data/test.crt \ + anchor:FILE:$srcdir/data/ca.crt \ + crl:FILE:$srcdir/data/crl1.der > /dev/null || exit 1 + +echo "crl revoked cert" +${hxtool} verify \ + cert:FILE:$srcdir/data/revoke.crt \ + anchor:FILE:$srcdir/data/ca.crt \ + crl:FILE:$srcdir/data/crl1.der > /dev/null && exit 1 + +if ${hxtool} info | grep 'ecdsa: hcrypto null' > /dev/null ; then + echo "not testing ECDSA since hcrypto doesnt support ECDSA" +else + echo "eccert -> root" + ${hxtool} verify --missing-revoke \ + cert:FILE:$srcdir/data/secp256r2TestServer.cert.pem \ + anchor:FILE:$srcdir/data/secp256r1TestCA.cert.pem > /dev/null || exit 1 + + echo "eccert -> root" + ${hxtool} verify --missing-revoke \ + cert:FILE:$srcdir/data/secp256r2TestClient.cert.pem \ + anchor:FILE:$srcdir/data/secp256r1TestCA.cert.pem > /dev/null || exit 1 +fi + +echo "proxy cert" +${hxtool} verify --missing-revoke \ + --allow-proxy-certificate \ + cert:FILE:$srcdir/data/proxy-test.crt \ + chain:FILE:$srcdir/data/test.crt \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null || exit 1 + +echo "proxy cert (negative)" +${hxtool} verify --missing-revoke \ + cert:FILE:$srcdir/data/proxy-test.crt \ + chain:FILE:$srcdir/data/test.crt \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null && exit 1 + +echo "proxy cert (level fail)" +${hxtool} verify --missing-revoke \ + --allow-proxy-certificate \ + cert:FILE:$srcdir/data/proxy-level-test.crt \ + chain:FILE:$srcdir/data/proxy-test.crt \ + chain:FILE:$srcdir/data/test.crt \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null && exit 1 + +echo "not a proxy cert" +${hxtool} verify --missing-revoke \ + --allow-proxy-certificate \ + cert:FILE:$srcdir/data/no-proxy-test.crt \ + chain:FILE:$srcdir/data/test.crt \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null && exit 1 + +echo "proxy cert (max level 10)" +${hxtool} verify --missing-revoke \ + --allow-proxy-certificate \ + cert:FILE:$srcdir/data/proxy10-test.crt \ + chain:FILE:$srcdir/data/test.crt \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null || exit 1 + +echo "proxy cert (second level)" +${hxtool} verify --missing-revoke \ + --allow-proxy-certificate \ + cert:FILE:$srcdir/data/proxy10-child-test.crt \ + chain:FILE:$srcdir/data/proxy10-test.crt \ + chain:FILE:$srcdir/data/test.crt \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null || exit 1 + +echo "proxy cert (third level)" +${hxtool} verify --missing-revoke \ + --allow-proxy-certificate \ + cert:FILE:$srcdir/data/proxy10-child-child-test.crt \ + chain:FILE:$srcdir/data/proxy10-child-test.crt \ + chain:FILE:$srcdir/data/proxy10-test.crt \ + chain:FILE:$srcdir/data/test.crt \ + anchor:FILE:$srcdir/data/ca.crt > /dev/null || exit 1 + +exit 0 diff --git a/third_party/heimdal/lib/hx509/test_cms.in b/third_party/heimdal/lib/hx509/test_cms.in new file mode 100644 index 0000000..8b3de76 --- /dev/null +++ b/third_party/heimdal/lib/hx509/test_cms.in @@ -0,0 +1,514 @@ +#!/bin/sh +# +# Copyright (c) 2005 Kungliga Tekniska Högskolan +# (Royal Institute of Technology, Stockholm, Sweden). +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Institute nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $Id$ +# + +srcdir="@srcdir@" +objdir="@objdir@" + +stat="--statistic-file=${objdir}/statfile" + +hxtool="${TESTS_ENVIRONMENT} ./hxtool ${stat}" + +if ${hxtool} info | grep 'rsa: hcrypto null RSA' > /dev/null ; then + exit 77 +fi +if ${hxtool} info | grep 'rand: not available' > /dev/null ; then + exit 77 +fi + +if ${hxtool} info | grep 'ecdsa: hcrypto null' > /dev/null ; then + echo "not testing ECDSA since hcrypto doesnt support ECDSA" +else + echo "create signed data (ec)" + ${hxtool} cms-create-sd \ + --certificate=FILE:$srcdir/data/secp256r2TestClient.pem \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null || exit 1 + + echo "verify signed data (ec)" + ${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/secp256r1TestCA.cert.pem \ + sd.data sd.data.out > /dev/null || exit 1 + cmp "$srcdir/test_chain.in" sd.data.out || exit 1 +fi + +echo "create signed data" +${hxtool} cms-create-sd \ + --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null || exit 1 + +echo "verify signed data" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + sd.data sd.data.out > /dev/null || exit 1 +cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + +echo "create signed data (no signer)" +${hxtool} cms-create-sd \ + --no-signer \ + --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null || exit 1 + +echo "verify signed data (no signer)" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --no-signer-allowed \ + --anchors=FILE:$srcdir/data/ca.crt \ + sd.data sd.data.out > signer.tmp || exit 1 +cmp "$srcdir/test_chain.in" sd.data.out || exit 1 +grep "unsigned" signer.tmp > /dev/null || exit 1 + +echo "verify signed data (no signer) (test failure)" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + sd.data sd.data.out 2> signer.tmp && exit 1 +grep "No signers where found" signer.tmp > /dev/null || exit 1 + +echo "create signed data (id-by-name)" +${hxtool} cms-create-sd \ + --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ + --id-by-name \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null || exit 1 + +echo "verify signed data" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + sd.data sd.data.out > /dev/null || exit 1 +cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + +echo "verify signed data (EE cert as anchor)" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/test.crt \ + sd.data sd.data.out > /dev/null || exit 1 +cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + +echo "create signed data (password)" +${hxtool} cms-create-sd \ + --pass=PASS:foobar \ + --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test-pw.key \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null || exit 1 + +echo "verify signed data" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + sd.data sd.data.out > /dev/null || exit 1 +cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + +echo "create signed data (combined)" +${hxtool} cms-create-sd \ + --certificate=FILE:$srcdir/data/test.combined.crt \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null || exit 1 + +echo "verify signed data" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + sd.data sd.data.out > /dev/null || exit 1 +cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + +echo "create signed data (content info)" +${hxtool} cms-create-sd \ + --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ + --content-info \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null || exit 1 + +echo "verify signed data (content info)" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + --content-info \ + sd.data sd.data.out > /dev/null || exit 1 +cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + +echo "create signed data (content type)" +${hxtool} cms-create-sd \ + --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ + --content-type=1.1.1.1 \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null || exit 1 + +echo "verify signed data (content type)" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + sd.data sd.data.out > /dev/null || exit 1 +cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + +echo "create signed data (pem)" +${hxtool} cms-create-sd \ + --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ + --pem \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null || exit 1 + +echo "verify signed data (pem)" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + --pem \ + sd.data sd.data.out > /dev/null +cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + +echo "create signed data (pem, detached)" +${hxtool} cms-create-sd \ + --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ + --detached-signature \ + --pem \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null || exit 1 + +echo "verify signed data (pem, detached)" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + --pem \ + --signed-content="$srcdir/test_chain.in" \ + sd.data sd.data.out > /dev/null +cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + +echo "create signed data (p12)" +${hxtool} cms-create-sd \ + --pass=PASS:foobar \ + --certificate=PKCS12:$srcdir/data/test.p12 \ + --signer=friendlyname-test \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null || exit 1 + +echo "verify signed data" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + --content-info \ + "$srcdir/data/test-signed-data" sd.data.out > /dev/null || exit 1 +cmp "$srcdir/data/static-file" sd.data.out || exit 1 + +echo "verify signed data (no attr)" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + --content-info \ + "$srcdir/data/test-signed-data-noattr" sd.data.out > /dev/null || exit 1 +cmp "$srcdir/data/static-file" sd.data.out || exit 1 + +echo "verify failure signed data (no attr, no certs)" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + --content-info \ + "$srcdir/data/test-signed-data-noattr-nocerts" \ + sd.data.out > /dev/null 2>/dev/null && exit 1 + +echo "verify signed data (no attr, no certs)" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + --certificate=FILE:$srcdir/data/test.crt \ + --content-info \ + "$srcdir/data/test-signed-data-noattr-nocerts" \ + sd.data.out > /dev/null || exit 1 +cmp "$srcdir/data/static-file" sd.data.out || exit 1 + +echo "verify signed data - sha1" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + --content-info \ + "$srcdir/data/test-signed-sha-1" sd.data.out > /dev/null || exit 1 +cmp "$srcdir/data/static-file" sd.data.out || exit 1 + +echo "verify signed data - sha256" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + --content-info \ + "$srcdir/data/test-signed-sha-256" sd.data.out > /dev/null || exit 1 +cmp "$srcdir/data/static-file" sd.data.out || exit 1 + +#echo "verify signed data - sha512" +#${hxtool} cms-verify-sd \ +# --missing-revoke \ +# --anchors=FILE:$srcdir/data/ca.crt \ +# --content-info \ +# "$srcdir/data/test-signed-sha-512" sd.data.out > /dev/null || exit 1 +#cmp "$srcdir/data/static-file" sd.data.out || exit 1 + + +echo "create signed data (subcert, no certs)" +${hxtool} cms-create-sd \ + --certificate=FILE:$srcdir/data/sub-cert.crt,$srcdir/data/sub-cert.key \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null || exit 1 + +echo "verify failure signed data" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + sd.data sd.data.out > /dev/null 2> /dev/null && exit 1 + +echo "verify success signed data" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --certificate=FILE:$srcdir/data/sub-ca.crt \ + --anchors=FILE:$srcdir/data/ca.crt \ + sd.data sd.data.out > /dev/null || exit 1 +cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + +echo "create signed data (subcert, certs)" +${hxtool} cms-create-sd \ + --certificate=FILE:$srcdir/data/sub-cert.crt,$srcdir/data/sub-cert.key \ + --pool=FILE:$srcdir/data/sub-ca.crt \ + --anchors=FILE:$srcdir/data/ca.crt \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null || exit 1 + +echo "verify success signed data" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + sd.data sd.data.out > /dev/null || exit 1 +cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + +echo "create signed data (subcert, certs, no-root)" +${hxtool} cms-create-sd \ + --certificate=FILE:$srcdir/data/sub-cert.crt,$srcdir/data/sub-cert.key \ + --pool=FILE:$srcdir/data/sub-ca.crt \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null || exit 1 + +echo "verify success signed data" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + sd.data sd.data.out > /dev/null || exit 1 +cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + +echo "create signed data (subcert, no-subca, no-root)" +${hxtool} cms-create-sd \ + --certificate=FILE:$srcdir/data/sub-cert.crt,$srcdir/data/sub-cert.key \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null || exit 1 + +echo "verify failure signed data" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + sd.data sd.data.out > /dev/null 2>/dev/null && exit 1 + +echo "create signed data (sd cert)" +${hxtool} cms-create-sd \ + --certificate=FILE:$srcdir/data/test-ds-only.crt,$srcdir/data/test-ds-only.key \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null || exit 1 + +echo "create signed data (ke cert)" +${hxtool} cms-create-sd \ + --certificate=FILE:$srcdir/data/test-ke-only.crt,$srcdir/data/test-ke-only.key \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null 2>/dev/null && exit 1 + +echo "create signed data (sd + ke certs)" +${hxtool} cms-create-sd \ + --certificate=FILE:$srcdir/data/test-ke-only.crt,$srcdir/data/test-ke-only.key \ + --certificate=FILE:$srcdir/data/test-ds-only.crt,$srcdir/data/test-ds-only.key \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null || exit 1 + +echo "create signed data (ke + sd certs)" +${hxtool} cms-create-sd \ + --certificate=FILE:$srcdir/data/test-ds-only.crt,$srcdir/data/test-ds-only.key \ + --certificate=FILE:$srcdir/data/test-ke-only.crt,$srcdir/data/test-ke-only.key \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null || exit 1 + +echo "create signed data (detached)" +${hxtool} cms-create-sd \ + --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ + --detached-signature \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null || exit 1 + +echo "verify signed data (detached)" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --signed-content="$srcdir/test_chain.in" \ + --anchors=FILE:$srcdir/data/ca.crt \ + sd.data sd.data.out > /dev/null || exit 1 +cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + +echo "verify failure signed data (detached)" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + sd.data sd.data.out > /dev/null 2>/dev/null && exit 1 + +echo "create signed data (rsa)" +${hxtool} cms-create-sd \ + --peer-alg=1.2.840.113549.1.1.1 \ + --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ + "$srcdir/test_chain.in" \ + sd.data > /dev/null || exit 1 + +echo "verify signed data (rsa)" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + sd.data sd.data.out > /dev/null 2>/dev/null || exit 1 +cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + +echo "create signed data (pem, detached)" +cp "$srcdir/test_chain.in" sd +${hxtool} cms-sign \ + --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ + --detached-signature \ + --pem \ + sd > /dev/null || exit 1 + +echo "verify signed data (pem, detached)" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:$srcdir/data/ca.crt \ + --pem \ + sd.pem > /dev/null + +echo "create signed data (no certs, detached sig)" +cp "$srcdir/test_chain.in" sd +${hxtool} cms-sign \ + --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ + --detached-signature \ + --no-embedded-certs \ + "$srcdir/data/static-file" \ + sd > /dev/null || exit 1 + +echo "create signed data (leif only, detached sig)" +cp "$srcdir/test_chain.in" sd +${hxtool} cms-sign \ + --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ + --detached-signature \ + --embed-leaf-only \ + "$srcdir/data/static-file" \ + sd > /dev/null || exit 1 + +echo "create signed data (no certs, detached sig, 2 signers)" +cp "$srcdir/test_chain.in" sd +${hxtool} cms-sign \ + --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ + --certificate=FILE:$srcdir/data/sub-cert.crt,$srcdir/data/sub-cert.key \ + --detached-signature \ + --no-embedded-certs \ + "$srcdir/data/static-file" \ + sd > /dev/null || exit 1 + +echo "create signed data (no certs, detached sig, 3 signers)" +cp "$srcdir/test_chain.in" sd +${hxtool} cms-sign \ + --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ + --certificate=FILE:$srcdir/data/sub-cert.crt,$srcdir/data/sub-cert.key \ + --certificate=FILE:$srcdir/data/test-ds-only.crt,$srcdir/data/test-ds-only.key \ + --detached-signature \ + --no-embedded-certs \ + "$srcdir/data/static-file" \ + sd > /dev/null || exit 1 + +echo "envelope data (content-type)" +${hxtool} cms-envelope \ + --certificate=FILE:$srcdir/data/test.crt \ + --content-type=1.1.1.1 \ + "$srcdir/data/static-file" \ + ev.data > /dev/null || exit 1 + +echo "unenvelope data (content-type)" +${hxtool} cms-unenvelope \ + --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ + ev.data ev.data.out \ + FILE:$srcdir/data/test.crt,$srcdir/data/test.key > /dev/null || exit 1 +cmp "$srcdir/data/static-file" ev.data.out || exit 1 + +echo "envelope data (content-info)" +${hxtool} cms-envelope \ + --certificate=FILE:$srcdir/data/test.crt \ + --content-info \ + "$srcdir/data/static-file" \ + ev.data > /dev/null || exit 1 + +echo "unenvelope data (content-info)" +${hxtool} cms-unenvelope \ + --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ + --content-info \ + ev.data ev.data.out \ + FILE:$srcdir/data/test.crt,$srcdir/data/test.key > /dev/null || exit 1 +cmp "$srcdir/data/static-file" ev.data.out || exit 1 + +for a in des-ede3 aes-128 aes-256; do + + rm -f ev.data ev.data.out + echo "envelope data ($a)" + ${hxtool} cms-envelope \ + --encryption-type="$a-cbc" \ + --certificate=FILE:$srcdir/data/test.crt \ + "$srcdir/data/static-file" \ + ev.data || exit 1 + + echo "unenvelope data ($a)" + ${hxtool} cms-unenvelope \ + --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ + ev.data ev.data.out > /dev/null || exit 1 + cmp "$srcdir/data/static-file" ev.data.out || exit 1 +done + +for a in rc2-40 rc2-64 rc2-128 des-ede3 aes-128 aes-256; do + echo "static unenvelope data ($a)" + + rm -f ev.data.out + ${hxtool} cms-unenvelope \ + --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ + --content-info \ + --allow-weak \ + "$srcdir/data/test-enveloped-$a" ev.data.out > /dev/null || exit 1 + cmp "$srcdir/data/static-file" ev.data.out || exit 1 +done + +exit 0 diff --git a/third_party/heimdal/lib/hx509/test_crypto.in b/third_party/heimdal/lib/hx509/test_crypto.in new file mode 100644 index 0000000..9206031 --- /dev/null +++ b/third_party/heimdal/lib/hx509/test_crypto.in @@ -0,0 +1,192 @@ +#!/bin/sh +# +# Copyright (c) 2006 Kungliga Tekniska Högskolan +# (Royal Institute of Technology, Stockholm, Sweden). +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Institute nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $Id$ +# + +srcdir="@srcdir@" +objdir="@objdir@" + +stat="--statistic-file=${objdir}/statfile" + +hxtool="${TESTS_ENVIRONMENT} ./hxtool ${stat}" + +if ${hxtool} info | grep 'rsa: hcrypto null RSA' > /dev/null ; then + exit 77 +fi +if ${hxtool} info | grep 'rand: not available' > /dev/null ; then + exit 77 +fi + + +echo "Bleichenbacher good cert (from eay)" +${hxtool} verify --missing-revoke \ + --time=2006-09-25 \ + cert:FILE:$srcdir/data/bleichenbacher-good.pem \ + anchor:FILE:$srcdir/data/bleichenbacher-good.pem > /dev/null || exit 1 + +echo "Bleichenbacher bad cert (from eay)" +${hxtool} verify --missing-revoke \ + --time=2006-09-25 \ + cert:FILE:$srcdir/data/bleichenbacher-bad.pem \ + anchor:FILE:$srcdir/data/bleichenbacher-bad.pem > /dev/null && exit 1 + +echo "Bleichenbacher good cert (from yutaka)" +${hxtool} verify --missing-revoke \ + --time=2006-09-25 \ + cert:FILE:$srcdir/data/yutaka-pad-ok-cert.pem \ + anchor:FILE:$srcdir/data/yutaka-pad-ok-ca.pem > /dev/null || exit 1 + +echo "Bleichenbacher bad cert (from yutaka)" +${hxtool} verify --missing-revoke \ + --time=2006-09-25 \ + cert:FILE:$srcdir/data/yutaka-pad-broken-cert.pem \ + anchor:FILE:$srcdir/data/yutaka-pad-broken-ca.pem > /dev/null && exit 1 + +# Ralf-Philipp Weinmann <weinmann@cdc.informatik.tu-darmstadt.de> +# Andrew Pyshkin <pychkine@cdc.informatik.tu-darmstadt.de> +echo "Bleichenbacher bad cert (sf pad correct)" +${hxtool} verify --missing-revoke \ + --time=2006-09-25 \ + cert:FILE:$srcdir/data/bleichenbacher-sf-pad-correct.pem \ + anchor:FILE:$srcdir/data/sf-class2-root.pem > /dev/null && exit 1 + +echo Read 50 kilobyte random data +${hxtool} random-data 50kilobyte > random-data || exit 1 + +echo "crypto select1" +${hxtool} crypto-select > test || { echo "select1"; exit 1; } +cmp test ${srcdir}/tst-crypto-select1 > /dev/null || \ + { echo "select1 failure"; exit 1; } + +echo "crypto select1" +${hxtool} crypto-select --type=digest > test || { echo "select1"; exit 1; } +cmp test ${srcdir}/tst-crypto-select1 > /dev/null || \ + { echo "select1 failure"; exit 1; } + +echo "crypto select2" +${hxtool} crypto-select --type=public-sig > test || { echo "select2"; exit 1; } +cmp test ${srcdir}/tst-crypto-select2 > /dev/null || \ + { echo "select2 failure"; exit 1; } + +echo "crypto select3" +${hxtool} crypto-select \ + --type=public-sig \ + --peer-cmstype=1.2.840.113549.1.1.4 \ + > test || { echo "select3"; exit 1; } +cmp test ${srcdir}/tst-crypto-select3 > /dev/null || \ + { echo "select3 failure"; exit 1; } + +echo "crypto select4" +${hxtool} crypto-select \ + --type=public-sig \ + --peer-cmstype=1.2.840.113549.1.1.5 \ + --peer-cmstype=1.2.840.113549.1.1.4 \ + > test || { echo "select4"; exit 1; } +cmp test ${srcdir}/tst-crypto-select4 > /dev/null || \ + { echo "select4 failure"; exit 1; } + +echo "crypto select5" +${hxtool} crypto-select \ + --type=public-sig \ + --peer-cmstype=1.2.840.113549.1.1.11 \ + --peer-cmstype=1.2.840.113549.1.1.5 \ + > test || { echo "select5"; exit 1; } +cmp test ${srcdir}/tst-crypto-select5 > /dev/null || \ + { echo "select5 failure"; exit 1; } + +echo "crypto select6" +${hxtool} crypto-select \ + --type=public-sig \ + --peer-cmstype=1.2.840.113549.2.5 \ + --peer-cmstype=1.2.840.113549.1.1.5 \ + > test || { echo "select6"; exit 1; } +cmp test ${srcdir}/tst-crypto-select6 > /dev/null || \ + { echo "select6 failure"; exit 1; } + +echo "crypto select7" +${hxtool} crypto-select \ + --type=secret \ + --peer-cmstype=2.16.840.1.101.3.4.1.42 \ + --peer-cmstype=1.2.840.113549.3.7 \ + --peer-cmstype=1.2.840.113549.1.1.5 \ + > test || { echo "select7"; exit 1; } +cmp test ${srcdir}/tst-crypto-select7 > /dev/null || \ + { echo "select7 failure"; exit 1; } + +#echo "crypto available1" +#${hxtool} crypto-available \ +# --type=all \ +# > test || { echo "available1"; exit 1; } +#cmp test ${srcdir}/tst-crypto-available1 > /dev/null || \ +# { echo "available1 failure"; exit 1; } + +echo "crypto available2" +${hxtool} crypto-available \ + --type=digest \ + > test || { echo "available2"; exit 1; } +cmp test ${srcdir}/tst-crypto-available2 > /dev/null || \ + { echo "available2 failure"; exit 1; } + +#echo "crypto available3" +#${hxtool} crypto-available \ +# --type=public-sig \ +# > test || { echo "available3"; exit 1; } +#cmp test ${srcdir}/tst-crypto-available3 > /dev/null || \ +# { echo "available3 failure"; exit 1; } + +echo "copy keystore FILE existing -> FILE" +${hxtool} certificate-copy \ + FILE:${srcdir}/data/test.crt,${srcdir}/data/test.key \ + FILE:out.pem || exit 1 + +echo "copy keystore FILE -> FILE" +${hxtool} certificate-copy \ + FILE:out.pem \ + FILE:out2.pem || exit 1 + +echo "copy keystore FILE -> PKCS12" +${hxtool} certificate-copy \ + FILE:out.pem \ + PKCS12:out2.pem || exit 1 + +echo "print certificate with utf8" +${hxtool} print \ + FILE:$srcdir/data/j.pem >/dev/null 2>/dev/null || exit 1 + +echo "Make sure that we can parse EC private keys" +${hxtool} print --content \ + FILE:$srcdir/data/pkinit-ec.crt,$srcdir/data/pkinit-ec.key \ + > /dev/null || exit 1 + +exit 0 diff --git a/third_party/heimdal/lib/hx509/test_expr.c b/third_party/heimdal/lib/hx509/test_expr.c new file mode 100644 index 0000000..8c2c0a5 --- /dev/null +++ b/third_party/heimdal/lib/hx509/test_expr.c @@ -0,0 +1,87 @@ + +#include "hx_locl.h" +#include <err.h> + +struct foo { + int val; + char *str; +} foo[] = { + { 0, "FALSE" }, + { 1, "TRUE" }, + { 0, "!TRUE" }, + { 0, "! TRUE" }, + { 0, "!\tTRUE" }, + { 0, "( FALSE AND FALSE )" }, + { 0, "( TRUE AND FALSE )" }, + { 1, "( TRUE AND TRUE )" }, + { 1, "( TRUE OR TRUE )" }, + { 1, "( TRUE OR FALSE )" }, + { 0, "( FALSE OR FALSE )" }, + { 1, "! ( FALSE OR FALSE )" }, + + { 1, "\"foo\" TAILMATCH \"foo\"" }, + { 1, "\"foobar\" TAILMATCH \"bar\"" }, + { 0, "\"foobar\" TAILMATCH \"foo\"" }, + + { 1, "\"foo\" == \"foo\"" }, + { 0, "\"foo\" == \"bar\"" }, + { 0, "\"foo\" != \"foo\"" }, + { 1, "\"foo\" != \"bar\"" }, + { 1, "%{variable} == \"foo\"" }, + { 0, "%{variable} == \"bar\"" }, + { 1, "%{context.variable} == \"foo\"" }, + { 0, "%{context.variable} == \"bar\"" }, + { 1, "\"foo\" IN ( \"bar\", \"foo\")" }, + { 0, "\"foo\" IN ( \"bar\", \"baz\")" }, + { 0, "\"bar\" IN %{context}" }, + { 1, "\"foo\" IN %{context}" }, + { 1, "\"variable\" IN %{context}" }, + + { 1, "\"foo\" IN %{context} AND %{context.variable} == \"foo\"" } +}; + +int +main(int argc, char **argv) +{ + struct hx_expr *expr; + hx509_context context; + hx509_env env = NULL, env2 = NULL; + int val, i, ret; + +#if 0 + extern int yydebug; + yydebug = 1; +#endif + + ret = hx509_context_init(&context); + if (ret) + errx(1, "hx509_context_init failed with %d", ret); + + hx509_env_add(context, &env, "variable", "foo"); + hx509_env_add(context, &env2, "variable", "foo"); + hx509_env_add_binding(context, &env, "context", env2); + + for (i = 0; i < sizeof(foo)/sizeof(foo[0]); i++) { + + expr = _hx509_expr_parse(foo[i].str); + if (expr == NULL) + errx(1, "_hx509_expr_parse failed for %d: %s", i, foo[i].str); + + val = _hx509_expr_eval(context, env, expr); + if (foo[i].val) { + if (val == 0) + errx(1, "_hx509_expr_eval not true when it should: %d: %s", + i, foo[i].str); + } else { + if (val) + errx(1, "_hx509_expr_eval true when it should not: %d: %s", + i, foo[i].str); + } + + _hx509_expr_free(expr); + } + + hx509_env_free(&env); + + return 0; +} diff --git a/third_party/heimdal/lib/hx509/test_java_pkcs11.in b/third_party/heimdal/lib/hx509/test_java_pkcs11.in new file mode 100644 index 0000000..9a843a4 --- /dev/null +++ b/third_party/heimdal/lib/hx509/test_java_pkcs11.in @@ -0,0 +1,73 @@ +#!/bin/sh +# +# Copyright (c) 2008 Kungliga Tekniska Högskolan +# (Royal Institute of Technology, Stockholm, Sweden). +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Institute nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +exit 0 + +srcdir="@srcdir@" +objdir="@objdir@" + +dir=$objdir +file= + +for a in libhx509.so .libs/libhx509.so libhx509.dylib .libs/libhx509.dylib ; do + if [ -f $dir/$a ] ; then + file=$dir/$a + break + fi +done + +if [ "X$file" = X ] ; then + exit 0 +fi + +cat > pkcs11.cfg <<EOF +name = Heimdal +library = $file +EOF + +cat > test-rc-file.rc <<EOF +certificate cert User certificate FILE:$srcdir/data/test.crt,$srcdir/data/test.key +debug stdout +EOF + + +env SOFTPKCS11RC="test-rc-file.rc" \ + keytool \ + -keystore NONE \ + -storetype PKCS11 \ + -providerClass sun.security.pkcs11.SunPKCS11 \ + -providerArg pkcs11.cfg \ + -list || exit 1 + +exit 0 diff --git a/third_party/heimdal/lib/hx509/test_name.c b/third_party/heimdal/lib/hx509/test_name.c new file mode 100644 index 0000000..ba4cbaa --- /dev/null +++ b/third_party/heimdal/lib/hx509/test_name.c @@ -0,0 +1,468 @@ +/* + * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" + +static int +test_name(hx509_context context, const char *name) +{ + hx509_name n; + char *s; + int ret; + + ret = hx509_parse_name(context, name, &n); + if (ret) + return 1; + + ret = hx509_name_to_string(n, &s); + if (ret) + return 1; + + if (strcmp(s, name) != 0) + return 1; + + hx509_name_free(&n); + free(s); + + return 0; +} + +static int +test_name_fail(hx509_context context, const char *name) +{ + hx509_name n; + + if (hx509_parse_name(context, name, &n) == HX509_NAME_MALFORMED) + return 0; + hx509_name_free(&n); + return 1; +} + +static int +test_expand(hx509_context context, const char *name, const char *expected) +{ + hx509_env env = NULL; + hx509_name n; + char *s; + int ret; + + hx509_env_add(context, &env, "uid", "lha"); + + ret = hx509_parse_name(context, name, &n); + if (ret) + return 1; + + ret = hx509_name_expand(context, n, env); + hx509_env_free(&env); + if (ret) + return 1; + + ret = hx509_name_to_string(n, &s); + hx509_name_free(&n); + if (ret) + return 1; + + ret = strcmp(s, expected) != 0; + free(s); + if (ret) + return 1; + + return 0; +} + +char certdata1[] = + "\x30\x82\x04\x1d\x30\x82\x03\x05\xa0\x03\x02\x01\x02\x02\x10\x4e" + "\x81\x2d\x8a\x82\x65\xe0\x0b\x02\xee\x3e\x35\x02\x46\xe5\x3d\x30" + "\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81" + "\x81\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1b" + "\x30\x19\x06\x03\x55\x04\x08\x13\x12\x47\x72\x65\x61\x74\x65\x72" + "\x20\x4d\x61\x6e\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0e\x06" + "\x03\x55\x04\x07\x13\x07\x53\x61\x6c\x66\x6f\x72\x64\x31\x1a\x30" + "\x18\x06\x03\x55\x04\x0a\x13\x11\x43\x4f\x4d\x4f\x44\x4f\x20\x43" + "\x41\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x27\x30\x25\x06\x03\x55" + "\x04\x03\x13\x1e\x43\x4f\x4d\x4f\x44\x4f\x20\x43\x65\x72\x74\x69" + "\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69" + "\x74\x79\x30\x1e\x17\x0d\x30\x36\x31\x32\x30\x31\x30\x30\x30\x30" + "\x30\x30\x5a\x17\x0d\x32\x39\x31\x32\x33\x31\x32\x33\x35\x39\x35" + "\x39\x5a\x30\x81\x81\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02" + "\x47\x42\x31\x1b\x30\x19\x06\x03\x55\x04\x08\x13\x12\x47\x72\x65" + "\x61\x74\x65\x72\x20\x4d\x61\x6e\x63\x68\x65\x73\x74\x65\x72\x31" + "\x10\x30\x0e\x06\x03\x55\x04\x07\x13\x07\x53\x61\x6c\x66\x6f\x72" + "\x64\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x13\x11\x43\x4f\x4d\x4f" + "\x44\x4f\x20\x43\x41\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x27\x30" + "\x25\x06\x03\x55\x04\x03\x13\x1e\x43\x4f\x4d\x4f\x44\x4f\x20\x43" + "\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74" + "\x68\x6f\x72\x69\x74\x79\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86" + "\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82" + "\x01\x0a\x02\x82\x01\x01\x00\xd0\x40\x8b\x8b\x72\xe3\x91\x1b\xf7" + "\x51\xc1\x1b\x54\x04\x98\xd3\xa9\xbf\xc1\xe6\x8a\x5d\x3b\x87\xfb" + "\xbb\x88\xce\x0d\xe3\x2f\x3f\x06\x96\xf0\xa2\x29\x50\x99\xae\xdb" + "\x3b\xa1\x57\xb0\x74\x51\x71\xcd\xed\x42\x91\x4d\x41\xfe\xa9\xc8" + "\xd8\x6a\x86\x77\x44\xbb\x59\x66\x97\x50\x5e\xb4\xd4\x2c\x70\x44" + "\xcf\xda\x37\x95\x42\x69\x3c\x30\xc4\x71\xb3\x52\xf0\x21\x4d\xa1" + "\xd8\xba\x39\x7c\x1c\x9e\xa3\x24\x9d\xf2\x83\x16\x98\xaa\x16\x7c" + "\x43\x9b\x15\x5b\xb7\xae\x34\x91\xfe\xd4\x62\x26\x18\x46\x9a\x3f" + "\xeb\xc1\xf9\xf1\x90\x57\xeb\xac\x7a\x0d\x8b\xdb\x72\x30\x6a\x66" + "\xd5\xe0\x46\xa3\x70\xdc\x68\xd9\xff\x04\x48\x89\x77\xde\xb5\xe9" + "\xfb\x67\x6d\x41\xe9\xbc\x39\xbd\x32\xd9\x62\x02\xf1\xb1\xa8\x3d" + "\x6e\x37\x9c\xe2\x2f\xe2\xd3\xa2\x26\x8b\xc6\xb8\x55\x43\x88\xe1" + "\x23\x3e\xa5\xd2\x24\x39\x6a\x47\xab\x00\xd4\xa1\xb3\xa9\x25\xfe" + "\x0d\x3f\xa7\x1d\xba\xd3\x51\xc1\x0b\xa4\xda\xac\x38\xef\x55\x50" + "\x24\x05\x65\x46\x93\x34\x4f\x2d\x8d\xad\xc6\xd4\x21\x19\xd2\x8e" + "\xca\x05\x61\x71\x07\x73\x47\xe5\x8a\x19\x12\xbd\x04\x4d\xce\x4e" + "\x9c\xa5\x48\xac\xbb\x26\xf7\x02\x03\x01\x00\x01\xa3\x81\x8e\x30" + "\x81\x8b\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x0b\x58\xe5" + "\x8b\xc6\x4c\x15\x37\xa4\x40\xa9\x30\xa9\x21\xbe\x47\x36\x5a\x56" + "\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01" + "\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01" + "\x01\xff\x30\x49\x06\x03\x55\x1d\x1f\x04\x42\x30\x40\x30\x3e\xa0" + "\x3c\xa0\x3a\x86\x38\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e" + "\x63\x6f\x6d\x6f\x64\x6f\x63\x61\x2e\x63\x6f\x6d\x2f\x43\x4f\x4d" + "\x4f\x44\x4f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e" + "\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x2e\x63\x72\x6c\x30\x0d\x06" + "\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01" + "\x00\x3e\x98\x9e\x9b\xf6\x1b\xe9\xd7\x39\xb7\x78\xae\x1d\x72\x18" + "\x49\xd3\x87\xe4\x43\x82\xeb\x3f\xc9\xaa\xf5\xa8\xb5\xef\x55\x7c" + "\x21\x52\x65\xf9\xd5\x0d\xe1\x6c\xf4\x3e\x8c\x93\x73\x91\x2e\x02" + "\xc4\x4e\x07\x71\x6f\xc0\x8f\x38\x61\x08\xa8\x1e\x81\x0a\xc0\x2f" + "\x20\x2f\x41\x8b\x91\xdc\x48\x45\xbc\xf1\xc6\xde\xba\x76\x6b\x33" + "\xc8\x00\x2d\x31\x46\x4c\xed\xe7\x9d\xcf\x88\x94\xff\x33\xc0\x56" + "\xe8\x24\x86\x26\xb8\xd8\x38\x38\xdf\x2a\x6b\xdd\x12\xcc\xc7\x3f" + "\x47\x17\x4c\xa2\xc2\x06\x96\x09\xd6\xdb\xfe\x3f\x3c\x46\x41\xdf" + "\x58\xe2\x56\x0f\x3c\x3b\xc1\x1c\x93\x35\xd9\x38\x52\xac\xee\xc8" + "\xec\x2e\x30\x4e\x94\x35\xb4\x24\x1f\x4b\x78\x69\xda\xf2\x02\x38" + "\xcc\x95\x52\x93\xf0\x70\x25\x59\x9c\x20\x67\xc4\xee\xf9\x8b\x57" + "\x61\xf4\x92\x76\x7d\x3f\x84\x8d\x55\xb7\xe8\xe5\xac\xd5\xf1\xf5" + "\x19\x56\xa6\x5a\xfb\x90\x1c\xaf\x93\xeb\xe5\x1c\xd4\x67\x97\x5d" + "\x04\x0e\xbe\x0b\x83\xa6\x17\x83\xb9\x30\x12\xa0\xc5\x33\x15\x05" + "\xb9\x0d\xfb\xc7\x05\x76\xe3\xd8\x4a\x8d\xfc\x34\x17\xa3\xc6\x21" + "\x28\xbe\x30\x45\x31\x1e\xc7\x78\xbe\x58\x61\x38\xac\x3b\xe2\x01" + "\x65"; + +char certdata2[] = + "\x30\x82\x03\x02\x30\x82\x02\x6b\x02\x10\x39\xca\x54\x89\xfe\x50" + "\x22\x32\xfe\x32\xd9\xdb\xfb\x1b\x84\x19\x30\x0d\x06\x09\x2a\x86" + "\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xc1\x31\x0b\x30\x09" + "\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55" + "\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e" + "\x63\x2e\x31\x3c\x30\x3a\x06\x03\x55\x04\x0b\x13\x33\x43\x6c\x61" + "\x73\x73\x20\x31\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d" + "\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f" + "\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x32" + "\x31\x3a\x30\x38\x06\x03\x55\x04\x0b\x13\x31\x28\x63\x29\x20\x31" + "\x39\x39\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e" + "\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69" + "\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x1f\x30\x1d" + "\x06\x03\x55\x04\x0b\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6e\x20" + "\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x30\x1e\x17" + "\x0d\x39\x38\x30\x35\x31\x38\x30\x30\x30\x30\x30\x30\x5a\x17\x0d" + "\x31\x38\x30\x35\x31\x38\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xc1" + "\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30" + "\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e" + "\x2c\x20\x49\x6e\x63\x2e\x31\x3c\x30\x3a\x06\x03\x55\x04\x0b\x13" + "\x33\x43\x6c\x61\x73\x73\x20\x31\x20\x50\x75\x62\x6c\x69\x63\x20" + "\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63" + "\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20" + "\x2d\x20\x47\x32\x31\x3a\x30\x38\x06\x03\x55\x04\x0b\x13\x31\x28" + "\x63\x29\x20\x31\x39\x39\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6e" + "\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74" + "\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79" + "\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x56\x65\x72\x69\x53" + "\x69\x67\x6e\x20\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72" + "\x6b\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01" + "\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xaa\xd0" + "\xba\xbe\x16\x2d\xb8\x83\xd4\xca\xd2\x0f\xbc\x76\x31\xca\x94\xd8" + "\x1d\x93\x8c\x56\x02\xbc\xd9\x6f\x1a\x6f\x52\x36\x6e\x75\x56\x0a" + "\x55\xd3\xdf\x43\x87\x21\x11\x65\x8a\x7e\x8f\xbd\x21\xde\x6b\x32" + "\x3f\x1b\x84\x34\x95\x05\x9d\x41\x35\xeb\x92\xeb\x96\xdd\xaa\x59" + "\x3f\x01\x53\x6d\x99\x4f\xed\xe5\xe2\x2a\x5a\x90\xc1\xb9\xc4\xa6" + "\x15\xcf\xc8\x45\xeb\xa6\x5d\x8e\x9c\x3e\xf0\x64\x24\x76\xa5\xcd" + "\xab\x1a\x6f\xb6\xd8\x7b\x51\x61\x6e\xa6\x7f\x87\xc8\xe2\xb7\xe5" + "\x34\xdc\x41\x88\xea\x09\x40\xbe\x73\x92\x3d\x6b\xe7\x75\x02\x03" + "\x01\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05" + "\x05\x00\x03\x81\x81\x00\x8b\xf7\x1a\x10\xce\x76\x5c\x07\xab\x83" + "\x99\xdc\x17\x80\x6f\x34\x39\x5d\x98\x3e\x6b\x72\x2c\xe1\xc7\xa2" + "\x7b\x40\x29\xb9\x78\x88\xba\x4c\xc5\xa3\x6a\x5e\x9e\x6e\x7b\xe3" + "\xf2\x02\x41\x0c\x66\xbe\xad\xfb\xae\xa2\x14\xce\x92\xf3\xa2\x34" + "\x8b\xb4\xb2\xb6\x24\xf2\xe5\xd5\xe0\xc8\xe5\x62\x6d\x84\x7b\xcb" + "\xbe\xbb\x03\x8b\x7c\x57\xca\xf0\x37\xa9\x90\xaf\x8a\xee\x03\xbe" + "\x1d\x28\x9c\xd9\x26\x76\xa0\xcd\xc4\x9d\x4e\xf0\xae\x07\x16\xd5" + "\xbe\xaf\x57\x08\x6a\xd0\xa0\x42\x42\x42\x1e\xf4\x20\xcc\xa5\x78" + "\x82\x95\x26\x38\x8a\x47"; + +char certdata3[] = + "\x30\x82\x04\x43\x30\x82\x03\x2b\xa0\x03\x02\x01\x02\x02\x01\x01" + "\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30" + "\x7f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1b" + "\x30\x19\x06\x03\x55\x04\x08\x0c\x12\x47\x72\x65\x61\x74\x65\x72" + "\x20\x4d\x61\x6e\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0e\x06" + "\x03\x55\x04\x07\x0c\x07\x53\x61\x6c\x66\x6f\x72\x64\x31\x1a\x30" + "\x18\x06\x03\x55\x04\x0a\x0c\x11\x43\x6f\x6d\x6f\x64\x6f\x20\x43" + "\x41\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x25\x30\x23\x06\x03\x55" + "\x04\x03\x0c\x1c\x54\x72\x75\x73\x74\x65\x64\x20\x43\x65\x72\x74" + "\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73" + "\x30\x1e\x17\x0d\x30\x34\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30" + "\x5a\x17\x0d\x32\x38\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5a" + "\x30\x7f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31" + "\x1b\x30\x19\x06\x03\x55\x04\x08\x0c\x12\x47\x72\x65\x61\x74\x65" + "\x72\x20\x4d\x61\x6e\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0e" + "\x06\x03\x55\x04\x07\x0c\x07\x53\x61\x6c\x66\x6f\x72\x64\x31\x1a" + "\x30\x18\x06\x03\x55\x04\x0a\x0c\x11\x43\x6f\x6d\x6f\x64\x6f\x20" + "\x43\x41\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x25\x30\x23\x06\x03" + "\x55\x04\x03\x0c\x1c\x54\x72\x75\x73\x74\x65\x64\x20\x43\x65\x72" + "\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65" + "\x73\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01" + "\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01" + "\x01\x00\xdf\x71\x6f\x36\x58\x53\x5a\xf2\x36\x54\x57\x80\xc4\x74" + "\x08\x20\xed\x18\x7f\x2a\x1d\xe6\x35\x9a\x1e\x25\xac\x9c\xe5\x96" + "\x7e\x72\x52\xa0\x15\x42\xdb\x59\xdd\x64\x7a\x1a\xd0\xb8\x7b\xdd" + "\x39\x15\xbc\x55\x48\xc4\xed\x3a\x00\xea\x31\x11\xba\xf2\x71\x74" + "\x1a\x67\xb8\xcf\x33\xcc\xa8\x31\xaf\xa3\xe3\xd7\x7f\xbf\x33\x2d" + "\x4c\x6a\x3c\xec\x8b\xc3\x92\xd2\x53\x77\x24\x74\x9c\x07\x6e\x70" + "\xfc\xbd\x0b\x5b\x76\xba\x5f\xf2\xff\xd7\x37\x4b\x4a\x60\x78\xf7" + "\xf0\xfa\xca\x70\xb4\xea\x59\xaa\xa3\xce\x48\x2f\xa9\xc3\xb2\x0b" + "\x7e\x17\x72\x16\x0c\xa6\x07\x0c\x1b\x38\xcf\xc9\x62\xb7\x3f\xa0" + "\x93\xa5\x87\x41\xf2\xb7\x70\x40\x77\xd8\xbe\x14\x7c\xe3\xa8\xc0" + "\x7a\x8e\xe9\x63\x6a\xd1\x0f\x9a\xc6\xd2\xf4\x8b\x3a\x14\x04\x56" + "\xd4\xed\xb8\xcc\x6e\xf5\xfb\xe2\x2c\x58\xbd\x7f\x4f\x6b\x2b\xf7" + "\x60\x24\x58\x24\xce\x26\xef\x34\x91\x3a\xd5\xe3\x81\xd0\xb2\xf0" + "\x04\x02\xd7\x5b\xb7\x3e\x92\xac\x6b\x12\x8a\xf9\xe4\x05\xb0\x3b" + "\x91\x49\x5c\xb2\xeb\x53\xea\xf8\x9f\x47\x86\xee\xbf\x95\xc0\xc0" + "\x06\x9f\xd2\x5b\x5e\x11\x1b\xf4\xc7\x04\x35\x29\xd2\x55\x5c\xe4" + "\xed\xeb\x02\x03\x01\x00\x01\xa3\x81\xc9\x30\x81\xc6\x30\x1d\x06" + "\x03\x55\x1d\x0e\x04\x16\x04\x14\xc5\x7b\x58\xbd\xed\xda\x25\x69" + "\xd2\xf7\x59\x16\xa8\xb3\x32\xc0\x7b\x27\x5b\xf4\x30\x0e\x06\x03" + "\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03" + "\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x81\x83" + "\x06\x03\x55\x1d\x1f\x04\x7c\x30\x7a\x30\x3c\xa0\x3a\xa0\x38\x86" + "\x36\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x63\x6f\x6d\x6f" + "\x64\x6f\x63\x61\x2e\x63\x6f\x6d\x2f\x54\x72\x75\x73\x74\x65\x64" + "\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x53\x65\x72\x76\x69" + "\x63\x65\x73\x2e\x63\x72\x6c\x30\x3a\xa0\x38\xa0\x36\x86\x34\x68" + "\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x63\x6f\x6d\x6f\x64\x6f" + "\x2e\x6e\x65\x74\x2f\x54\x72\x75\x73\x74\x65\x64\x43\x65\x72\x74" + "\x69\x66\x69\x63\x61\x74\x65\x53\x65\x72\x76\x69\x63\x65\x73\x2e" + "\x63\x72\x6c\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05" + "\x05\x00\x03\x82\x01\x01\x00\xc8\x93\x81\x3b\x89\xb4\xaf\xb8\x84" + "\x12\x4c\x8d\xd2\xf0\xdb\x70\xba\x57\x86\x15\x34\x10\xb9\x2f\x7f" + "\x1e\xb0\xa8\x89\x60\xa1\x8a\xc2\x77\x0c\x50\x4a\x9b\x00\x8b\xd8" + "\x8b\xf4\x41\xe2\xd0\x83\x8a\x4a\x1c\x14\x06\xb0\xa3\x68\x05\x70" + "\x31\x30\xa7\x53\x9b\x0e\xe9\x4a\xa0\x58\x69\x67\x0e\xae\x9d\xf6" + "\xa5\x2c\x41\xbf\x3c\x06\x6b\xe4\x59\xcc\x6d\x10\xf1\x96\x6f\x1f" + "\xdf\xf4\x04\x02\xa4\x9f\x45\x3e\xc8\xd8\xfa\x36\x46\x44\x50\x3f" + "\x82\x97\x91\x1f\x28\xdb\x18\x11\x8c\x2a\xe4\x65\x83\x57\x12\x12" + "\x8c\x17\x3f\x94\x36\xfe\x5d\xb0\xc0\x04\x77\x13\xb8\xf4\x15\xd5" + "\x3f\x38\xcc\x94\x3a\x55\xd0\xac\x98\xf5\xba\x00\x5f\xe0\x86\x19" + "\x81\x78\x2f\x28\xc0\x7e\xd3\xcc\x42\x0a\xf5\xae\x50\xa0\xd1\x3e" + "\xc6\xa1\x71\xec\x3f\xa0\x20\x8c\x66\x3a\x89\xb4\x8e\xd4\xd8\xb1" + "\x4d\x25\x47\xee\x2f\x88\xc8\xb5\xe1\x05\x45\xc0\xbe\x14\x71\xde" + "\x7a\xfd\x8e\x7b\x7d\x4d\x08\x96\xa5\x12\x73\xf0\x2d\xca\x37\x27" + "\x74\x12\x27\x4c\xcb\xb6\x97\xe9\xd9\xae\x08\x6d\x5a\x39\x40\xdd" + "\x05\x47\x75\x6a\x5a\x21\xb3\xa3\x18\xcf\x4e\xf7\x2e\x57\xb7\x98" + "\x70\x5e\xc8\xc4\x78\xb0\x62"; + + +static int +compare_subject(hx509_cert c1, hx509_cert c2, int *l) +{ + hx509_name n1, n2; + int ret; + + ret = hx509_cert_get_subject(c1, &n1); + if (ret) return 1; + ret = hx509_cert_get_subject(c2, &n2); + if (ret) return 1; + + *l = hx509_name_cmp(n1, n2); + hx509_name_free(&n1); + hx509_name_free(&n2); + + return 0; +} + +static int +test_compare(hx509_context context) +{ + int ret; + hx509_cert c1, c2, c3; + int l0, l1, l2, l3; + + /* check transative properties of name compare function */ + + c1 = hx509_cert_init_data(context, certdata1, sizeof(certdata1) - 1, NULL); + if (c1 == NULL) return 1; + + c2 = hx509_cert_init_data(context, certdata2, sizeof(certdata2) - 1, NULL); + if (c2 == NULL) return 1; + + c3 = hx509_cert_init_data(context, certdata3, sizeof(certdata3) - 1, NULL); + if (c3 == NULL) return 1; + + ret = compare_subject(c1, c1, &l0); + if (ret) return 1; + ret = compare_subject(c1, c2, &l1); + if (ret) return 1; + ret = compare_subject(c1, c3, &l2); + if (ret) return 1; + ret = compare_subject(c2, c3, &l3); + if (ret) return 1; + + if (l0 != 0) return 1; + if (l2 < l1) return 1; + if (l3 < l2) return 1; + if (l3 < l1) return 1; + + hx509_cert_free(c1); + hx509_cert_free(c2); + hx509_cert_free(c3); + + return 0; +} + +static int +test_pkinit_san(hx509_context context, const char *p, const char *realm, ...) +{ + KRB5PrincipalName kn; + GeneralName gn; + va_list ap; + size_t i, sz; + char *round_trip; + int ret; + + memset(&kn, 0, sizeof(kn)); + memset(&gn, 0, sizeof(gn)); + + ret = _hx509_make_pkinit_san(context, p, &gn.u.otherName.value); + if (ret == 0) + ret = decode_KRB5PrincipalName(gn.u.otherName.value.data, + gn.u.otherName.value.length, &kn, &sz); + if (ret) + return 1; + if (strcmp(realm, kn.realm) != 0) + return 1; + + va_start(ap, realm); + for (i = 0; i < kn.principalName.name_string.len; i++) { + const char *s = va_arg(ap, const char *); + + if (s == NULL || strcmp(kn.principalName.name_string.val[i], s) != 0) + return 1; + } + if (va_arg(ap, const char *) != NULL) + return 1; + va_end(ap); + + gn.element = choice_GeneralName_otherName; + gn.u.otherName.type_id.length = 0; + gn.u.otherName.type_id.components = 0; + ret = der_copy_oid(&asn1_oid_id_pkinit_san, &gn.u.otherName.type_id); + if (ret == 0) + ret = hx509_general_name_unparse(&gn, &round_trip); + if (ret) + return 1; + if (strncmp(round_trip, "otherName: 1.3.6.1.5.2.2 KerberosPrincipalName ", + sizeof("otherName: 1.3.6.1.5.2.2 KerberosPrincipalName ") - 1)) + return 1; + if (ret || strcmp(round_trip + sizeof("otherName: 1.3.6.1.5.2.2 KerberosPrincipalName ") - 1, p) != 0) + return 1; + free_KRB5PrincipalName(&kn); + free_GeneralName(&gn); + free(round_trip); + return 0; +} + +static int +test_pkinit_san_fail(hx509_context context, const char *p) +{ + heim_octet_string os; + KRB5PrincipalName kn; + int ret; + + memset(&kn, 0, sizeof(kn)); + ret = _hx509_make_pkinit_san(context, p, &os); + if (ret == 0) { + free(os.data); + return 1; + } + return 0; +} + + +int +main(int argc, char **argv) +{ + hx509_context context; + int ret = 0; + + ret = hx509_context_init(&context); + if (ret) + errx(1, "hx509_context_init failed with %d", ret); + + ret += test_name(context, "CN=foo,C=SE"); + ret += test_name(context, "CN=foo,CN=kaka,CN=FOO,DC=ad1,C=SE"); + ret += test_name(context, "1.2.3.4=foo,C=SE"); + ret += test_name_fail(context, "="); + ret += test_name_fail(context, "CN=foo,=foo"); + ret += test_name_fail(context, "CN=foo,really-unknown-type=foo"); + + ret += test_expand(context, "UID=${uid},C=SE", "UID=lha,C=SE"); + ret += test_expand(context, "UID=foo${uid},C=SE", "UID=foolha,C=SE"); + ret += test_expand(context, "UID=${uid}bar,C=SE", "UID=lhabar,C=SE"); + ret += test_expand(context, "UID=f${uid}b,C=SE", "UID=flhab,C=SE"); + ret += test_expand(context, "UID=${uid}${uid},C=SE", "UID=lhalha,C=SE"); + ret += test_expand(context, "UID=${uid}{uid},C=SE", "UID=lha{uid},C=SE"); + + ret += test_compare(context); + + ret += test_pkinit_san(context, "foo@BAR.H5L.SE", + "BAR.H5L.SE", "foo", NULL); + ret += test_pkinit_san(context, "foo\\ bar@BAR.H5L.SE", + "BAR.H5L.SE", "foo bar", NULL); + ret += test_pkinit_san(context, "foo\\/bar@BAR.H5L.SE", + "BAR.H5L.SE", "foo/bar", NULL); + ret += test_pkinit_san(context, "foo/bar@BAR.H5L.SE", + "BAR.H5L.SE", "foo", "bar", NULL); + ret += test_pkinit_san(context, "foo\\tbar@BAR.H5L.SE", + "BAR.H5L.SE", "foo\tbar", NULL); + ret += test_pkinit_san(context, "foo\\nbar@BAR.H5L.SE", + "BAR.H5L.SE", "foo\nbar", NULL); + ret += test_pkinit_san(context, "foo@\\ BAR.H5L.SE", + " BAR.H5L.SE", "foo", NULL); + ret += test_pkinit_san(context, "foo@\\nBAR.H5L.SE", + "\nBAR.H5L.SE", "foo", NULL); + ret += test_pkinit_san_fail(context, "foo\\0bar@BAR.H5L.SE"); + + hx509_context_free(&context); + + return !!ret; +} diff --git a/third_party/heimdal/lib/hx509/test_nist.in b/third_party/heimdal/lib/hx509/test_nist.in new file mode 100644 index 0000000..09034fe --- /dev/null +++ b/third_party/heimdal/lib/hx509/test_nist.in @@ -0,0 +1,117 @@ +#!/bin/sh +# +# Copyright (c) 2004 - 2005 Kungliga Tekniska Högskolan +# (Royal Institute of Technology, Stockholm, Sweden). +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Institute nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $Id$ +# + +srcdir="@srcdir@" +objdir="@objdir@" +nistdir=${objdir}/PKITS_data +nistzip=${srcdir}/data/PKITS_data.zip + +stat="--statistic-file=${objdir}/statfile" + +hxtool="${TESTS_ENVIRONMENT} ./hxtool ${stat}" + +# nistzip is not distributed part of the distribution +test -f "$nistzip" || exit 77 + +if ${hxtool} info | grep 'rsa: hcrypto null RSA' > /dev/null ; then + exit 77 +fi +if ${hxtool} info | grep 'rand: not available' > /dev/null ; then + exit 77 +fi + +echo "nist tests" + +if [ ! -d "$nistdir" ] ; then + ( mkdir "$nistdir" && unzip -d "${nistdir}" "${nistzip}" ) >/dev/null || \ + { rm -rf "$nistdir" ; exit 1; } +fi + +ec=0 +while read id verify cert arg1 arg2 arg3 arg4 arg5 ; do + expr "$id" : "#" > /dev/null && continue + + test "$id" = "end" && break + + args="" + case "$arg1" in + *.crt) args="$args chain:FILE:$nistdir/certs/$arg1" ;; + *.crl) args="$args crl:FILE:$nistdir/crls/$arg1" ;; + *) args="$args $arg1" ;; + esac + case "$arg2" in + *.crt) args="$args chain:FILE:$nistdir/certs/$arg2" ;; + *.crl) args="$args crl:FILE:$nistdir/crls/$arg2" ;; + *) args="$args $arg2" ;; + esac + case "$arg3" in + *.crt) args="$args chain:FILE:$nistdir/certs/$arg3" ;; + *.crl) args="$args crl:FILE:$nistdir/crls/$arg3" ;; + *) args="$args $arg3" ;; + esac + case "$arg4" in + *.crt) args="$args chain:FILE:$nistdir/certs/$arg4" ;; + *.crl) args="$args crl:FILE:$nistdir/crls/$arg4" ;; + *) args="$args $arg4" ;; + esac + case "$arg5" in + *.crt) args="$args chain:FILE:$nistdir/certs/$arg5" ;; + *.crl) args="$args crl:FILE:$nistdir/crls/$arg5" ;; + *) args="$args $arg5" ;; + esac + + args="$args anchor:FILE:$nistdir/certs/TrustAnchorRootCertificate.crt" + args="$args crl:FILE:$nistdir/crls/TrustAnchorRootCRL.crl" + args="$args cert:FILE:$nistdir/certs/$cert" + + if ${hxtool} verify --time=2008-05-20 $args > /dev/null; then + if test "$verify" = "f"; then + echo ${hxtool} verify --time=2008-05-20 $args + echo "verify passed on fail: $id $cert" + ec=1 + fi + elif test "$verify" = "p"; then + echo ${hxtool} verify --time=2008-05-20 $args + echo "verify failed on pass: $id $cert" + ec=1 + fi + +done < $srcdir/data/nist-data + + +echo "done!" + +exit $ec diff --git a/third_party/heimdal/lib/hx509/test_nist2.in b/third_party/heimdal/lib/hx509/test_nist2.in new file mode 100644 index 0000000..0c4276b --- /dev/null +++ b/third_party/heimdal/lib/hx509/test_nist2.in @@ -0,0 +1,136 @@ +#!/bin/sh +# +# Copyright (c) 2004 - 2008 Kungliga Tekniska Högskolan +# (Royal Institute of Technology, Stockholm, Sweden). +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Institute nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $Id: test_nist.in 21787 2007-08-02 08:50:24Z lha $ +# + +srcdir="@srcdir@" +objdir="@objdir@" +nistdir=${objdir}/PKITS_data +nistzip=${srcdir}/data/PKITS_data.zip +egrep="@egrep@" + +limit="${1:-nolimit}" + +stat="--statistic-file=${objdir}/statfile" + +hxtool="${TESTS_ENVIRONMENT} ./hxtool ${stat}" + +# nistzip is not distributed part of the distribution +test -f "$nistzip" || exit 77 + +if ${hxtool} info | grep 'rsa: hcrypto null RSA' > /dev/null ; then + exit 77 +fi +if ${hxtool} info | grep 'rand: not available' > /dev/null ; then + exit 77 +fi + +#--------- Try to find unzip + +oldifs=$IFS +IFS=: +set -- $PATH +IFS=$oldifs +found= + +for p in "$@" ; do + test -x "$p/unzip" && { found=1 ; break; } +done +test "X$found" = "X" && exit 77 + +#--------- + + +echo "nist tests, version 2" + +if [ ! -d "$nistdir" ] ; then + ( mkdir "$nistdir" && unzip -d "${nistdir}" "${nistzip}" ) >/dev/null || \ + { rm -rf "$nistdir" ; exit 1; } +fi + +ec= +name= +description= +while read result cert other ; do + if expr "$result" : "#" > /dev/null; then + name=${cert} + description="${other}" + continue + fi + + test nolimit != "${limit}" && ! expr "$name" : "$limit" > /dev/null && continue + + test "$result" = "end" && break + + args= + args="$args cert:FILE:$nistdir/certs/$cert" + args="$args chain:DIR:$nistdir/certs" + args="$args anchor:FILE:$nistdir/certs/TrustAnchorRootCertificate.crt" + + for a in $nistdir/crls/*.crl; do + args="$args crl:FILE:$a" + done + + cmd="${hxtool} verify --time=2008-05-20 $args" + eval ${cmd} > /dev/null + res=$? + + case "${result},${res}" in + 0,0) r="PASSs";; + 0,*) r="FAILs";; + [123],0) r="FAILf";; + [123],*) r="PASSf";; + *) echo="unknown result ${result},${res}" ; exit 1 ;; + esac + if ${egrep} "^${name} FAIL" $srcdir/data/nist-result2 > /dev/null; then + if expr "$r" : "PASS" >/dev/null; then + echo "${name} passed when expected not to" + echo "# ${description}" > nist2-passed-${name}.tmp + ec=1 + fi + elif ${egrep} "^${name} EITHER" $srcdir/data/nist-result2 > /dev/null; then + : + elif expr "$r" : "FAIL.*" >/dev/null ; then + echo "$r ${name} ${description}" + echo "# ${description}" > nist2-failed-${name}.tmp + echo "$cmd" >> nist2-failed-${name}.tmp + ec=1 + fi + +done < $srcdir/data/nist-data2 + + +echo "done!" + +exit $ec diff --git a/third_party/heimdal/lib/hx509/test_nist_cert.in b/third_party/heimdal/lib/hx509/test_nist_cert.in new file mode 100644 index 0000000..8c683d6 --- /dev/null +++ b/third_party/heimdal/lib/hx509/test_nist_cert.in @@ -0,0 +1,68 @@ +#!/bin/sh +# +# Copyright (c) 2006 Kungliga Tekniska Högskolan +# (Royal Institute of Technology, Stockholm, Sweden). +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Institute nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $Id$ +# + +srcdir="@srcdir@" +objdir="@objdir@" +nistdir=${objdir}/PKITS_data +nistzip=${srcdir}/data/PKITS_data.zip + +# nistzip is not distributed part of the distribution +test -f "$nistzip" || exit 77 + +stat="--statistic-file=${objdir}/statfile" + +hxtool="${TESTS_ENVIRONMENT} ./hxtool ${stat}" + +if ${hxtool} info | grep 'rsa: hcrypto null RSA' > /dev/null ; then + exit 77 +fi +if ${hxtool} info | grep 'rand: not available' > /dev/null ; then + exit 77 +fi + +if [ ! -d "$nistdir" ] ; then + ( mkdir "$nistdir" && cd "$nistdir" && unzip "$nistzip" ) >/dev/null || \ + { rm -rf "$nistdir" ; exit 1; } +fi + +if ${hxtool} validate DIR:$nistdir/certs > /dev/null; then + : +else + echo "validate failed" + exit 1 +fi + +exit 0 diff --git a/third_party/heimdal/lib/hx509/test_nist_pkcs12.in b/third_party/heimdal/lib/hx509/test_nist_pkcs12.in new file mode 100644 index 0000000..7898eee --- /dev/null +++ b/third_party/heimdal/lib/hx509/test_nist_pkcs12.in @@ -0,0 +1,77 @@ +#!/bin/sh +# +# Copyright (c) 2004 - 2005 Kungliga Tekniska Högskolan +# (Royal Institute of Technology, Stockholm, Sweden). +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Institute nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $Id$ +# + +srcdir="@srcdir@" +objdir="@objdir@" +pass="--pass=PASS:password" +nistdir=${objdir}/PKITS_data +nistzip=${srcdir}/data/PKITS_data.zip + +# nistzip is not distributed part of the distribution +test -f "$nistzip" || exit 77 + +stat="--statistic-file=${objdir}/statfile" + +hxtool="${TESTS_ENVIRONMENT} ./hxtool ${stat}" + +if ${hxtool} info | grep 'rsa: hcrypto null RSA' > /dev/null ; then + exit 77 +fi +if ${hxtool} info | grep 'rand: not available' > /dev/null ; then + exit 77 +fi + +if [ ! -d "$nistdir" ] ; then + ( mkdir "$nistdir" && cd "$nistdir" && unzip "$nistzip" ) >/dev/null || \ + { rm -rf "$nistdir" ; exit 1; } +fi + +echo "nist pkcs12 tests" + +for a in $nistdir/pkcs12/*.p12 ; do + + if ${hxtool} validate $pass PKCS12:$a > /dev/null; then + : + else + echo "$a failed" + exit 1 + fi + +done + +echo "done!" + +exit 0
\ No newline at end of file diff --git a/third_party/heimdal/lib/hx509/test_pkcs11.in b/third_party/heimdal/lib/hx509/test_pkcs11.in new file mode 100644 index 0000000..278296a --- /dev/null +++ b/third_party/heimdal/lib/hx509/test_pkcs11.in @@ -0,0 +1,62 @@ +#!/bin/sh +# +# Copyright (c) 2008 Kungliga Tekniska Högskolan +# (Royal Institute of Technology, Stockholm, Sweden). +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Institute nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +srcdir="@srcdir@" +objdir="@objdir@" + +SOFTPKCS11RC="test-rc-file.rc" \ +export SOFTPKCS11RC + +echo "password less" + +cat > test-rc-file.rc <<EOF +certificate cert User certificate FILE:$srcdir/data/test.crt,$srcdir/data/test.key +debug p11dbg.log +app-fatal true +EOF + +./test_soft_pkcs11 || exit 1 + +echo "password" + +cat > test-rc-file.rc <<EOF +certificate cert User certificate FILE:$srcdir/data/test.crt,$srcdir/data/test-pw.key +debug p11dbg.log +app-fatal true +EOF + +./test_soft_pkcs11 || exit 1 + +echo "done" +exit 0 diff --git a/third_party/heimdal/lib/hx509/test_query.in b/third_party/heimdal/lib/hx509/test_query.in new file mode 100644 index 0000000..d29d78a --- /dev/null +++ b/third_party/heimdal/lib/hx509/test_query.in @@ -0,0 +1,203 @@ +#!/bin/sh +# +# Copyright (c) 2005 - 2008 Kungliga Tekniska Högskolan +# (Royal Institute of Technology, Stockholm, Sweden). +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Institute nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $Id$ +# + +srcdir="@srcdir@" +objdir="@objdir@" + +stat="--statistic-file=${objdir}/statfile" + +hxtool="${TESTS_ENVIRONMENT} ./hxtool ${stat}" + +echo "try printing" +${hxtool} print \ + --pass=PASS:foobar \ + --info --content \ + PKCS12:$srcdir/data/test.p12 >/dev/null 2>/dev/null || exit 1 + +echo "try printing" +${hxtool} print \ + --pass=PASS:foobar \ + --info --content \ + FILE:$srcdir/data/kdc.crt >/dev/null 2>/dev/null || exit 1 + +${hxtool} print \ + --pass=PASS:foobar \ + --info \ + PKCS12:$srcdir/data/test.p12 >/dev/null 2>/dev/null || exit 1 + +echo "make sure entry is found (friendlyname)" +${hxtool} query \ + --pass=PASS:foobar \ + --friendlyname=friendlyname-test \ + PKCS12:$srcdir/data/test.p12 >/dev/null 2>/dev/null || exit 1 + +echo "make sure entry is not found (friendlyname)" +${hxtool} query \ + --pass=PASS:foobar \ + --friendlyname=friendlyname-test-not \ + PKCS12:$srcdir/data/test.p12 >/dev/null 2>/dev/null && exit 1 + +echo "make sure entry is found (eku)" +${hxtool} query \ + --eku=1.3.6.1.5.2.3.5 \ + FILE:$srcdir/data/kdc.crt >/dev/null 2>/dev/null || exit 1 + +echo "make sure entry is not found (eku)" +${hxtool} query \ + --eku=1.3.6.1.5.2.3.6 \ + FILE:$srcdir/data/kdc.crt >/dev/null 2>/dev/null && exit 1 + +echo "make sure entry is found (friendlyname, no-pw)" +${hxtool} query \ + --friendlyname=friendlyname-cert \ + PKCS12:$srcdir/data/test-nopw.p12 >/dev/null 2>/dev/null || exit 1 + +echo "check for ca cert (friendlyname)" +${hxtool} query \ + --pass=PASS:foobar \ + --friendlyname=ca \ + PKCS12:$srcdir/data/test.p12 >/dev/null 2>/dev/null || exit 1 + +echo "make sure entry is not found (friendlyname)" +${hxtool} query \ + --pass=PASS:foobar \ + --friendlyname=friendlyname-test \ + PKCS12:$srcdir/data/sub-cert.p12 >/dev/null 2>/dev/null && exit 1 + +echo "make sure entry is found (friendlyname|private key)" +${hxtool} query \ + --pass=PASS:foobar \ + --friendlyname=friendlyname-test \ + --private-key \ + PKCS12:$srcdir/data/test.p12 > /dev/null || exit 1 + +echo "make sure entry is not found (friendlyname|private key)" +${hxtool} query \ + --pass=PASS:foobar \ + --friendlyname=ca \ + --private-key \ + PKCS12:$srcdir/data/test.p12 >/dev/null 2>/dev/null && exit 1 + +echo "make sure entry is found (cert ds)" +${hxtool} query \ + --digitalSignature \ + FILE:$srcdir/data/test.crt >/dev/null 2>/dev/null || exit 1 + +echo "make sure entry is found (cert ke)" +${hxtool} query \ + --keyEncipherment \ + FILE:$srcdir/data/test.crt >/dev/null 2>/dev/null || exit 1 + +echo "make sure entry is found (cert ke + ds)" +${hxtool} query \ + --digitalSignature \ + --keyEncipherment \ + FILE:$srcdir/data/test.crt >/dev/null 2>/dev/null || exit 1 + +echo "make sure entry is found (cert-ds ds)" +${hxtool} query \ + --digitalSignature \ + FILE:$srcdir/data/test-ds-only.crt >/dev/null 2>/dev/null || exit 1 + +echo "make sure entry is not found (cert-ds ke)" +${hxtool} query \ + --keyEncipherment \ + FILE:$srcdir/data/test-ds-only.crt >/dev/null 2>/dev/null && exit 1 + +echo "make sure entry is not found (cert-ds ke + ds)" +${hxtool} query \ + --digitalSignature \ + --keyEncipherment \ + FILE:$srcdir/data/test-ds-only.crt >/dev/null 2>/dev/null && exit 1 + +echo "make sure entry is not found (cert-ke ds)" +${hxtool} query \ + --digitalSignature \ + FILE:$srcdir/data/test-ke-only.crt >/dev/null 2>/dev/null && exit 1 + +echo "make sure entry is found (cert-ke ke)" +${hxtool} query \ + --keyEncipherment \ + FILE:$srcdir/data/test-ke-only.crt >/dev/null 2>/dev/null || exit 1 + +echo "make sure entry is not found (cert-ke ke + ds)" +${hxtool} query \ + --digitalSignature \ + --keyEncipherment \ + FILE:$srcdir/data/test-ke-only.crt >/dev/null 2>/dev/null && exit 1 + +echo "make sure entry is found (eku) in query language" +${hxtool} query \ + --expr='"1.3.6.1.5.2.3.5" IN %{certificate.eku}' \ + FILE:$srcdir/data/kdc.crt > /dev/null || exit 1 + +echo "make sure entry is not found (eku) in query language" +${hxtool} query \ + --expr='"1.3.6.1.5.2.3.6" IN %{certificate.eku}' \ + FILE:$srcdir/data/kdc.crt > /dev/null && exit 1 + +echo "make sure entry is found (subject) in query language" +${hxtool} query \ + --expr='%{certificate.subject} == "CN=kdc,C=SE"' \ + FILE:$srcdir/data/kdc.crt > /dev/null || exit 1 + +echo "make sure entry is found using TAILMATCH (subject) in query language" +${hxtool} query \ + --expr='%{certificate.subject} TAILMATCH "C=SE"' \ + FILE:$srcdir/data/kdc.crt > /dev/null || exit 1 + +echo "make sure entry is not found using TAILMATCH (subject) in query language" +${hxtool} query \ + --expr='%{certificate.subject} TAILMATCH "C=FI"' \ + FILE:$srcdir/data/kdc.crt > /dev/null && exit 1 + +echo "make sure entry is found (issuer) in query language" +${hxtool} query \ + --expr='%{certificate.issuer} == "C=SE,CN=hx509 Test Root CA"' \ + FILE:$srcdir/data/kdc.crt > /dev/null || exit 1 + +echo "make sure entry match with EKU and TAILMATCH in query language" +${hxtool} query \ + --expr='"1.3.6.1.5.2.3.5" IN %{certificate.eku} AND %{certificate.subject} TAILMATCH "C=SE"' \ + FILE:$srcdir/data/kdc.crt > /dev/null || exit 1 + +echo "make sure entry match with hash.sha1" +${hxtool} query \ + --expr='"%{certificate.hash.sha1}EQ "412120212A2CBFD777DE5499ECB4724345F33F16"' \ + FILE:$srcdir/data/kdc.crt > /dev/null || exit 1 + + +exit 0 diff --git a/third_party/heimdal/lib/hx509/test_req.in b/third_party/heimdal/lib/hx509/test_req.in new file mode 100644 index 0000000..a070b1d --- /dev/null +++ b/third_party/heimdal/lib/hx509/test_req.in @@ -0,0 +1,135 @@ +#!/bin/sh +# +# Copyright (c) 2005 - 2007 Kungliga Tekniska Högskolan +# (Royal Institute of Technology, Stockholm, Sweden). +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Institute nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $Id$ +# + +srcdir="@srcdir@" +objdir="@objdir@" + +stat="--statistic-file=${objdir}/statfile" + +hxtool="${TESTS_ENVIRONMENT} ./hxtool ${stat}" + +if ${hxtool} info | grep 'rsa: hcrypto null RSA' > /dev/null ; then + exit 77 +fi +if ${hxtool} info | grep 'rand: not available' > /dev/null ; then + exit 77 +fi + +${hxtool} request-create \ + --subject="CN=Love,DC=it,DC=su,DC=se" \ + --key="FILE:$srcdir/data/key.der" \ + "${objdir}/request.out" || exit 1 + +${hxtool} request-print \ + PKCS10:request.out > /dev/null || exit 1 + +${hxtool} request-create \ + --subject="CN=Love,DC=it,DC=su,DC=se" \ + --eku=1.2.3.4.5.6.7 --eku=1.2.3.4.5.6.8 \ + --registered=1.2.3.4.5.6.9 --eku=1.2.3.4.5.6.10 \ + --dnsname=nutcracker.test.h5l.se \ + --dnsname=foo.nutcracker.test.h5l.se \ + --kerberos=HTTP/foo.nutcracker.it.su.se@TEST.H5L.SE \ + --kerberos=host/foo.nutcracker.it.su.se@TEST.H5L.SE \ + --email=foo@test.h5l.se \ + --key="FILE:$srcdir/data/key.der" \ + "${objdir}/request.out" || exit 1 + +cat > "$objdir/expected" <<EOF +request print +PKCS#10 CertificationRequest: + name: CN=Love,DC=it,DC=su,DC=se + eku: {1.2.3.4.5.6.7}, {1.2.3.4.5.6.8}, {1.2.3.4.5.6.10} + san: rfc822Name: foo@test.h5l.se + san: dNSName: nutcracker.test.h5l.se + san: dNSName: foo.nutcracker.test.h5l.se + san: pkinit: HTTP/foo.nutcracker.it.su.se@TEST.H5L.SE + san: pkinit: host/foo.nutcracker.it.su.se@TEST.H5L.SE + san: registeredID: 1.2.3.4.5.6.9 +EOF + +# Check that we got what we wanted: +${hxtool} request-print \ + PKCS10:request.out > "${objdir}/actual" || exit 1 + +diff "$objdir/expected" "${objdir}/actual" || exit 1 + +# Check that OpenSSL can parse our request: +if openssl version > /dev/null; then + openssl req -inform DER -in "${objdir}/request.out" -text | head -25 > "${objdir}/actual" + + # Various versions of openssl differ slightly in their text output for our + # CSR. Figure out what to expect: + if grep "Version: 0" "${objdir}/actual" > /dev/null; then + v=0 + else + v=1 + fi + if grep "RSA Public-Key:" "${objdir}/actual" > /dev/null; then + k="RSA " + else + k="" + fi + # Note interpolation of $v and $k in the here doc below: + cat > "$objdir/expected" <<EOF +Certificate Request: + Data: + Version: $v (0x0) + Subject: DC = se, DC = su, DC = it, CN = Love + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + ${k}Public-Key: (1024 bit) + Modulus: + 00:c2:aa:a2:42:b7:5b:99:a3:fd:ba:f0:9b:75:db: + ef:3c:9b:8c:cf:63:5f:46:d8:95:be:09:4a:a7:76: + 79:77:61:30:ef:0b:98:d2:47:ea:9c:09:b9:b9:b7: + 15:ac:4b:9c:2d:3f:f0:d9:99:9d:4d:5a:68:67:24: + 58:5e:65:60:13:9f:4d:dc:2f:03:1d:cd:e9:b6:33: + c2:5c:c6:de:c9:93:6c:ec:8d:9a:67:0e:dd:31:20: + ac:91:39:7a:c1:8f:39:65:ff:b3:1f:cf:7a:aa:79: + 8b:ed:eb:ad:a0:be:01:10:4c:5a:a7:47:1d:c6:ee: + 79:39:5c:c7:11:6c:b9:e7:2b + Exponent: 65537 (0x10001) + Attributes: + Requested Extensions: + X509v3 Extended Key Usage: critical + 1.2.3.4.5.6.7, 1.2.3.4.5.6.8, 1.2.3.4.5.6.10 + X509v3 Subject Alternative Name: + email:foo@test.h5l.se, DNS:nutcracker.test.h5l.se, DNS:foo.nutcracker.test.h5l.se, othername:<unsupported>, othername:<unsupported>, Registered ID:1.2.3.4.5.6.9 + Signature Algorithm: sha256WithRSAEncryption +EOF + diff -w "${objdir}/expected" "${objdir}/actual" || exit 1 +fi diff --git a/third_party/heimdal/lib/hx509/test_soft_pkcs11.c b/third_party/heimdal/lib/hx509/test_soft_pkcs11.c new file mode 100644 index 0000000..cdffcf8 --- /dev/null +++ b/third_party/heimdal/lib/hx509/test_soft_pkcs11.c @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hx_locl.h" +#include "ref/pkcs11.h" +#include <err.h> + +static CK_FUNCTION_LIST_PTR func; + + +static CK_RV +find_object(CK_SESSION_HANDLE session, + char *id, + CK_OBJECT_CLASS key_class, + CK_OBJECT_HANDLE_PTR object) +{ + CK_ULONG object_count; + CK_RV ret; + CK_ATTRIBUTE search_data[] = { + {CKA_ID, id, 0 }, + {CKA_CLASS, &key_class, sizeof(key_class)} + }; + CK_ULONG num_search_data = sizeof(search_data)/sizeof(search_data[0]); + + search_data[0].ulValueLen = strlen(id); + + ret = (*func->C_FindObjectsInit)(session, search_data, num_search_data); + if (ret != CKR_OK) + return ret; + + ret = (*func->C_FindObjects)(session, object, 1, &object_count); + if (ret != CKR_OK) + return ret; + if (object_count == 0) { + printf("found no object\n"); + return 1; + } + + ret = (*func->C_FindObjectsFinal)(session); + if (ret != CKR_OK) + return ret; + + return CKR_OK; +} + +static char *sighash = "hej"; +static char signature[1024]; + + +int +main(int argc, char **argv) +{ + CK_SLOT_ID_PTR slot_ids; + CK_SLOT_ID slot; + CK_ULONG num_slots; + CK_RV ret; + CK_SLOT_INFO slot_info; + CK_TOKEN_INFO token_info; + CK_SESSION_HANDLE session; + CK_OBJECT_HANDLE public, private; + + ret = C_GetFunctionList(&func); + if (ret != CKR_OK) + errx(1, "C_GetFunctionList failed: %d", (int)ret); + + (*func->C_Initialize)(NULL_PTR); + + ret = (*func->C_GetSlotList)(FALSE, NULL, &num_slots); + if (ret != CKR_OK) + errx(1, "C_GetSlotList1 failed: %d", (int)ret); + + if (num_slots == 0) + errx(1, "no slots"); + + if ((slot_ids = calloc(1, num_slots * sizeof(*slot_ids))) == NULL) + err(1, "alloc slots failed"); + + ret = (*func->C_GetSlotList)(FALSE, slot_ids, &num_slots); + if (ret != CKR_OK) + errx(1, "C_GetSlotList2 failed: %d", (int)ret); + + slot = slot_ids[0]; + free(slot_ids); + + ret = (*func->C_GetSlotInfo)(slot, &slot_info); + if (ret) + errx(1, "C_GetSlotInfo failed: %d", (int)ret); + + if ((slot_info.flags & CKF_TOKEN_PRESENT) == 0) + errx(1, "no token present"); + + ret = (*func->C_OpenSession)(slot, CKF_SERIAL_SESSION, + NULL, NULL, &session); + if (ret != CKR_OK) + errx(1, "C_OpenSession failed: %d", (int)ret); + + ret = (*func->C_GetTokenInfo)(slot, &token_info); + if (ret) + errx(1, "C_GetTokenInfo1 failed: %d", (int)ret); + + if (token_info.flags & CKF_LOGIN_REQUIRED) { + ret = (*func->C_Login)(session, CKU_USER, + (unsigned char*)"foobar", 6); + if (ret != CKR_OK) + errx(1, "C_Login failed: %d", (int)ret); + } + + ret = (*func->C_GetTokenInfo)(slot, &token_info); + if (ret) + errx(1, "C_GetTokenInfo2 failed: %d", (int)ret); + + if (token_info.flags & CKF_LOGIN_REQUIRED) + errx(1, "login required, even after C_Login"); + + ret = find_object(session, "cert", CKO_PUBLIC_KEY, &public); + if (ret != CKR_OK) + errx(1, "find cert failed: %d", (int)ret); + ret = find_object(session, "cert", CKO_PRIVATE_KEY, &private); + if (ret != CKR_OK) + errx(1, "find private key failed: %d", (int)ret); + + { + CK_ULONG ck_sigsize; + CK_MECHANISM mechanism; + + memset(&mechanism, 0, sizeof(mechanism)); + mechanism.mechanism = CKM_RSA_PKCS; + + ret = (*func->C_SignInit)(session, &mechanism, private); + if (ret != CKR_OK) + return 1; + + ck_sigsize = sizeof(signature); + ret = (*func->C_Sign)(session, (CK_BYTE *)sighash, strlen(sighash), + (CK_BYTE *)signature, &ck_sigsize); + if (ret != CKR_OK) { + printf("C_Sign failed with: %d\n", (int)ret); + return 1; + } + + ret = (*func->C_VerifyInit)(session, &mechanism, public); + if (ret != CKR_OK) + return 1; + + ret = (*func->C_Verify)(session, (CK_BYTE *)signature, ck_sigsize, + (CK_BYTE *)sighash, strlen(sighash)); + if (ret != CKR_OK) { + printf("message: %d\n", (int)ret); + return 1; + } + } + +#if 0 + { + CK_ULONG ck_sigsize, outsize; + CK_MECHANISM mechanism; + char outdata[1024]; + + memset(&mechanism, 0, sizeof(mechanism)); + mechanism.mechanism = CKM_RSA_PKCS; + + ret = (*func->C_EncryptInit)(session, &mechanism, public); + if (ret != CKR_OK) + return 1; + + ck_sigsize = sizeof(signature); + ret = (*func->C_Encrypt)(session, (CK_BYTE *)sighash, strlen(sighash), + (CK_BYTE *)signature, &ck_sigsize); + if (ret != CKR_OK) { + printf("message: %d\n", (int)ret); + return 1; + } + + ret = (*func->C_DecryptInit)(session, &mechanism, private); + if (ret != CKR_OK) + return 1; + + outsize = sizeof(outdata); + ret = (*func->C_Decrypt)(session, (CK_BYTE *)signature, ck_sigsize, + (CK_BYTE *)outdata, &outsize); + if (ret != CKR_OK) { + printf("message: %d\n", (int)ret); + return 1; + } + + if (ct_memcmp(sighash, outdata, strlen(sighash)) != 0) + return 1; + } +#endif + + ret = (*func->C_CloseSession)(session); + if (ret != CKR_OK) + return 1; + + (*func->C_Finalize)(NULL_PTR); + + return 0; +} diff --git a/third_party/heimdal/lib/hx509/test_windows.in b/third_party/heimdal/lib/hx509/test_windows.in new file mode 100644 index 0000000..c617f81 --- /dev/null +++ b/third_party/heimdal/lib/hx509/test_windows.in @@ -0,0 +1,89 @@ +#!/bin/sh +# +# Copyright (c) 2007 Kungliga Tekniska Högskolan +# (Royal Institute of Technology, Stockholm, Sweden). +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Institute nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $Id$ +# + +srcdir="@srcdir@" +objdir="@objdir@" + +stat="--statistic-file=${objdir}/statfile" + +hxtool="${TESTS_ENVIRONMENT} ./hxtool ${stat}" + +if ${hxtool} info | grep 'rsa: hcrypto null RSA' > /dev/null ; then + exit 77 +fi +if ${hxtool} info | grep 'rand: not available' > /dev/null ; then + exit 77 +fi + +echo "Create trust anchor" +${hxtool} issue-certificate \ + --self-signed \ + --issue-ca \ + --generate-key=rsa \ + --subject="CN=Windows-CA,DC=heimdal,DC=pki" \ + --lifetime=10years \ + --certificate="FILE:wca.pem" || exit 1 + +echo "Create domain controller cert" +${hxtool} issue-certificate \ + --type="pkinit-kdc" \ + --pk-init-principal="krbtgt/HEIMDAL.PKI@HEIMDAL.PKI" \ + --hostname=kdc.heimdal.pki \ + --generate-key=rsa \ + --subject="CN=kdc.heimdal.pki,dc=heimdal,dc=pki" \ + --certificate="FILE:wdc.pem" \ + --domain-controller \ + --crl-uri="http://www.test.h5l.se/test-hemdal-pki-crl1.crl" \ + --ca-certificate=FILE:wca.pem || exit 1 + + +echo "Create user cert" +${hxtool} issue-certificate \ + --type="pkinit-client" \ + --pk-init-principal="user@HEIMDAL.PKI" \ + --generate-key=rsa \ + --subject="CN=User,DC=heimdal,DC=pki" \ + --ms-upn="user@heimdal.pki" \ + --crl-uri="http://www.test.h5l.se/test-hemdal-pki-crl1.crl" \ + --certificate="FILE:wuser.pem" \ + --ca-certificate=FILE:wca.pem || exit 1 + +echo "Create crl" +${hxtool} crl-sign \ + --crl-file=wcrl.crl \ + --signer=FILE:wca.pem || exit 1 + +exit 0 diff --git a/third_party/heimdal/lib/hx509/tst-crypto-available1 b/third_party/heimdal/lib/hx509/tst-crypto-available1 new file mode 100644 index 0000000..71fa741 --- /dev/null +++ b/third_party/heimdal/lib/hx509/tst-crypto-available1 @@ -0,0 +1,13 @@ +1.2.840.113549.1.1.11 +1.2.840.113549.1.1.5 +1.2.840.113549.1.1.5 +1.2.840.113549.1.1.4 +1.2.840.113549.1.1.2 +1.2.752.43.16.1 +2.16.840.1.101.3.4.2.1 +1.3.14.3.2.26 +1.2.840.113549.2.5 +1.2.840.113549.2.2 +1.2.840.113549.3.7 +2.16.840.1.101.3.4.1.2 +2.16.840.1.101.3.4.1.42 diff --git a/third_party/heimdal/lib/hx509/tst-crypto-available2 b/third_party/heimdal/lib/hx509/tst-crypto-available2 new file mode 100644 index 0000000..22c0920 --- /dev/null +++ b/third_party/heimdal/lib/hx509/tst-crypto-available2 @@ -0,0 +1,5 @@ +2.16.840.1.101.3.4.2.3 +2.16.840.1.101.3.4.2.2 +2.16.840.1.101.3.4.2.1 +1.3.14.3.2.26 +1.2.840.113549.2.5 diff --git a/third_party/heimdal/lib/hx509/tst-crypto-available3 b/third_party/heimdal/lib/hx509/tst-crypto-available3 new file mode 100644 index 0000000..0b1a855 --- /dev/null +++ b/third_party/heimdal/lib/hx509/tst-crypto-available3 @@ -0,0 +1,6 @@ +1.2.840.113549.1.1.11 +1.2.840.113549.1.1.5 +1.2.840.113549.1.1.5 +1.2.840.113549.1.1.4 +1.2.840.113549.1.1.2 +1.2.752.43.16.1 diff --git a/third_party/heimdal/lib/hx509/tst-crypto-select b/third_party/heimdal/lib/hx509/tst-crypto-select new file mode 100644 index 0000000..399c883 --- /dev/null +++ b/third_party/heimdal/lib/hx509/tst-crypto-select @@ -0,0 +1 @@ +1.2.840.113549.1.1.11 diff --git a/third_party/heimdal/lib/hx509/tst-crypto-select1 b/third_party/heimdal/lib/hx509/tst-crypto-select1 new file mode 100644 index 0000000..c343b57 --- /dev/null +++ b/third_party/heimdal/lib/hx509/tst-crypto-select1 @@ -0,0 +1 @@ +2.16.840.1.101.3.4.2.1 diff --git a/third_party/heimdal/lib/hx509/tst-crypto-select2 b/third_party/heimdal/lib/hx509/tst-crypto-select2 new file mode 100644 index 0000000..399c883 --- /dev/null +++ b/third_party/heimdal/lib/hx509/tst-crypto-select2 @@ -0,0 +1 @@ +1.2.840.113549.1.1.11 diff --git a/third_party/heimdal/lib/hx509/tst-crypto-select3 b/third_party/heimdal/lib/hx509/tst-crypto-select3 new file mode 100644 index 0000000..ba9f29f --- /dev/null +++ b/third_party/heimdal/lib/hx509/tst-crypto-select3 @@ -0,0 +1 @@ +1.2.840.113549.1.1.4 diff --git a/third_party/heimdal/lib/hx509/tst-crypto-select4 b/third_party/heimdal/lib/hx509/tst-crypto-select4 new file mode 100644 index 0000000..749a549 --- /dev/null +++ b/third_party/heimdal/lib/hx509/tst-crypto-select4 @@ -0,0 +1 @@ +1.2.840.113549.1.1.5 diff --git a/third_party/heimdal/lib/hx509/tst-crypto-select5 b/third_party/heimdal/lib/hx509/tst-crypto-select5 new file mode 100644 index 0000000..399c883 --- /dev/null +++ b/third_party/heimdal/lib/hx509/tst-crypto-select5 @@ -0,0 +1 @@ +1.2.840.113549.1.1.11 diff --git a/third_party/heimdal/lib/hx509/tst-crypto-select6 b/third_party/heimdal/lib/hx509/tst-crypto-select6 new file mode 100644 index 0000000..749a549 --- /dev/null +++ b/third_party/heimdal/lib/hx509/tst-crypto-select6 @@ -0,0 +1 @@ +1.2.840.113549.1.1.5 diff --git a/third_party/heimdal/lib/hx509/tst-crypto-select7 b/third_party/heimdal/lib/hx509/tst-crypto-select7 new file mode 100644 index 0000000..9b0ac64 --- /dev/null +++ b/third_party/heimdal/lib/hx509/tst-crypto-select7 @@ -0,0 +1 @@ +2.16.840.1.101.3.4.1.42 diff --git a/third_party/heimdal/lib/hx509/version-script.map b/third_party/heimdal/lib/hx509/version-script.map new file mode 100644 index 0000000..a6c81da --- /dev/null +++ b/third_party/heimdal/lib/hx509/version-script.map @@ -0,0 +1,302 @@ +# $Id$ + +HEIMDAL_X509_1.2 { + global: + _hx509_cert_assign_key; + _hx509_cert_get_keyusage; + _hx509_cert_get_version; + _hx509_cert_private_key; + _hx509_certs_keys_free; + _hx509_certs_keys_get; + _hx509_expr_eval; + _hx509_expr_free; + _hx509_expr_parse; + _hx509_generate_private_key; + _hx509_generate_private_key_bits; + _hx509_generate_private_key_free; + _hx509_generate_private_key_init; + _hx509_generate_private_key_is_ca; + _hx509_get_cert; + _hx509_ks_type; + _hx509_make_pkinit_san; + _hx509_map_file_os; + _hx509_name_from_Name; + _hx509_private_key_export; + _hx509_private_key_exportable; + _hx509_private_key_get_internal; + _hx509_private_key_oid; + _hx509_private_key_ref; + hx509_request_add_GeneralName; + hx509_request_add_dns_name; + hx509_request_add_dns_srv; + hx509_request_add_eku; + hx509_request_add_email; + hx509_request_add_ms_upn_name; + hx509_request_add_pkinit; + hx509_request_add_registered; + hx509_request_add_xmpp_name; + hx509_request_authorize_ku; + hx509_request_authorize_eku; + hx509_request_authorize_san; + hx509_request_count_unsupported; + hx509_request_count_unauthorized; + hx509_request_print; + hx509_request_to_pkcs10; + _hx509_unmap_file_os; + _hx509_write_file; + hx509_bitstring_print; + _hx509_ca_issue_certificate; + hx509_ca_sign; + hx509_ca_sign_self; + hx509_ca_tbs_add_crl_dp_uri; + hx509_ca_tbs_add_eku; + hx509_ca_tbs_add_ku; + hx509_ca_tbs_add_pol; + hx509_ca_tbs_add_pol_mapping; + hx509_ca_tbs_add_san; + hx509_ca_tbs_add_san_dnssrv; + hx509_ca_tbs_add_san_hardwareModuleName; + hx509_ca_tbs_add_san_hardwareModuleName_string; + hx509_ca_tbs_add_san_hostname; + hx509_ca_tbs_add_san_jid; + hx509_ca_tbs_add_san_ms_upn; + hx509_ca_tbs_add_san_otherName; + hx509_ca_tbs_add_san_permanentIdentifier; + hx509_ca_tbs_add_san_permanentIdentifier_string; + hx509_ca_tbs_add_san_pkinit; + hx509_ca_tbs_add_san_rfc822name; + hx509_ca_tbs_free; + hx509_ca_tbs_get_name; + hx509_ca_tbs_init; + hx509_ca_tbs_set_ca; + hx509_ca_tbs_set_domaincontroller; + hx509_ca_tbs_set_from_csr; + hx509_ca_tbs_set_notAfter; + hx509_ca_tbs_set_notAfter_lifetime; + hx509_ca_tbs_set_notBefore; + hx509_ca_tbs_set_pkinit_max_life; + hx509_ca_tbs_set_proxy; + hx509_ca_tbs_set_serialnumber; + hx509_ca_tbs_set_spki; + hx509_ca_tbs_set_subject; + hx509_ca_tbs_set_template; + hx509_ca_tbs_set_unique; + hx509_ca_tbs_subject_expand; + hx509_ca_tbs_template_units; + hx509_cert; + hx509_cert_attribute; + hx509_cert_binary; + hx509_cert_check_eku; + hx509_cert_cmp; + hx509_cert_find_subjectAltName_otherName; + hx509_cert_free; + hx509_cert_get_SPKI; + hx509_cert_get_SPKI_AlgorithmIdentifier; + hx509_cert_get_attribute; + hx509_cert_get_base_subject; + hx509_cert_get_friendly_name; + hx509_cert_get_issuer; + hx509_cert_get_notAfter; + hx509_cert_get_notBefore; + hx509_cert_get_pkinit_max_life; + hx509_cert_get_serialnumber; + hx509_cert_get_subject; + hx509_cert_get_issuer_unique_id; + hx509_cert_get_subject_unique_id; + hx509_cert_have_private_key; + hx509_cert_have_private_key_only; + hx509_cert_init; + hx509_cert_init_data; + hx509_cert_init_private_key; + hx509_cert_keyusage_print; + hx509_cert_public_encrypt; + hx509_cert_ref; + hx509_cert_set_friendly_name; + hx509_certs_add; + hx509_certs_append; + hx509_certs_end_seq; + hx509_certs_destroy; + hx509_certs_ref; + hx509_certs_filter; + hx509_certs_find; + hx509_certs_free; + hx509_certs_info; + hx509_certs_init; + hx509_certs_iter; + hx509_certs_iter_f; + hx509_certs_merge; + hx509_certs_next_cert; + hx509_certs_start_seq; + hx509_certs_store; + hx509_ci_print_names; + hx509_clear_error_string; + hx509_cms_create_signed; + hx509_cms_create_signed_1; + hx509_cms_decrypt_encrypted; + hx509_cms_envelope_1; + hx509_cms_unenvelope; + hx509_cms_unwrap_ContentInfo; + hx509_cms_verify_signed; + hx509_cms_verify_signed_ext; + hx509_cms_wrap_ContentInfo; + hx509_context_free; + hx509_context_init; + hx509_context_set_missing_revoke; + hx509_crl_add_revoked_certs; + hx509_crl_alloc; + hx509_crl_free; + hx509_crl_lifetime; + hx509_crl_sign; + hx509_crypto_aes128_cbc; + hx509_crypto_aes256_cbc; + hx509_crypto_allow_weak; + hx509_crypto_available; + hx509_crypto_decrypt; + hx509_crypto_des_rsdi_ede3_cbc; + hx509_crypto_destroy; + hx509_crypto_encrypt; + hx509_crypto_enctype_by_name; + hx509_crypto_free_algs; + hx509_crypto_get_params; + hx509_crypto_init; + hx509_crypto_provider; + hx509_crypto_select; + hx509_crypto_set_key_data; + hx509_crypto_set_key_name; + hx509_crypto_set_padding; + hx509_crypto_set_params; + hx509_crypto_set_random_key; + hx509_empty_name; + hx509_env_add; + hx509_env_add_binding; + hx509_env_find; + hx509_env_find_binding; + hx509_env_free; + hx509_env_init; + hx509_env_lfind; + hx509_err; + hx509_free_error_string; + hx509_free_octet_string_list; + hx509_find_private_alg; + hx509_general_name_unparse; + hx509_get_error_string; + hx509_get_instance; + hx509_get_one_cert; + hx509_lock_add_cert; + hx509_lock_add_certs; + hx509_lock_add_password; + hx509_lock_command_string; + hx509_lock_free; + hx509_lock_init; + hx509_lock_prompt; + hx509_lock_reset_certs; + hx509_lock_reset_passwords; + hx509_lock_reset_promper; + hx509_lock_set_prompter; + hx509_name_binary; + hx509_name_cmp; + hx509_name_copy; + hx509_name_expand; + hx509_name_free; + hx509_name_is_null_p; + hx509_name_normalize; + hx509_name_to_Name; + hx509_name_to_string; + hx509_ocsp_request; + hx509_ocsp_verify; + hx509_oid_print; + hx509_oid_sprint; + hx509_parse_name; + hx509_parse_private_key; + hx509_peer_info_add_cms_alg; + hx509_peer_info_alloc; + hx509_peer_info_free; + hx509_peer_info_set_cert; + hx509_peer_info_set_cms_algs; + hx509_pem_add_header; + hx509_pem_find_header; + hx509_pem_free_header; + hx509_pem_read; + hx509_pem_write; + hx509_print_stdout; + hx509_print_cert; + hx509_private_key_assign_rsa; + hx509_private_key_free; + hx509_private_key_private_decrypt; + hx509_private_key_init; + hx509_private_key2SPKI; + hx509_prompt_hidden; + hx509_query_alloc; + hx509_query_free; + hx509_query_match_cmp_func; + hx509_query_match_eku; + hx509_query_match_expr; + hx509_query_match_friendly_name; + hx509_query_match_issuer_serial; + hx509_query_match_option; + hx509_query_statistic_file; + hx509_query_unparse_stats; + hx509_request_get_eku; + hx509_request_get_exts; + hx509_request_get_ku; + hx509_request_get_name; + hx509_request_get_san; + hx509_request_get_SubjectPublicKeyInfo; + hx509_request_free; + hx509_request_init; + hx509_request_parse; + hx509_request_parse_der; + hx509_request_set_ku; + hx509_request_set_name; + hx509_request_set_SubjectPublicKeyInfo; + hx509_revoke_add_crl; + hx509_revoke_add_ocsp; + hx509_revoke_free; + hx509_revoke_init; + hx509_revoke_ocsp_print; + hx509_revoke_verify; + hx509_revoke_print; + hx509_set_error_string; + hx509_set_error_stringv; + hx509_signature_md5; + hx509_signature_rsa; + hx509_signature_rsa_with_md5; + hx509_signature_rsa_with_sha1; + hx509_signature_rsa_with_sha256; + hx509_signature_rsa_with_sha384; + hx509_signature_rsa_with_sha512; + hx509_signature_sha1; + hx509_signature_sha256; + hx509_signature_sha384; + hx509_signature_sha512; + hx509_unparse_der_name; + hx509_validate_cert; + hx509_validate_ctx_add_flags; + hx509_validate_ctx_free; + hx509_validate_ctx_init; + hx509_validate_ctx_set_print; + hx509_verify_attach_anchors; + hx509_verify_attach_revoke; + hx509_verify_ctx_f_allow_default_trustanchors; + hx509_verify_destroy_ctx; + hx509_verify_hostname; + hx509_verify_init_ctx; + hx509_verify_path; + hx509_verify_set_max_depth; + hx509_verify_set_proxy_certificate; + hx509_verify_set_strict_rfc3280_verification; + hx509_verify_set_time; + hx509_verify_signature; + hx509_xfree; + initialize_hx_error_table_r; + # pkcs11 symbols + C_GetFunctionList; + local: + *; +}; + +HEIMDAL_X509_1.3 { + global: + hx509_ca_tbs_set_signature_algorithm; +}; + |