diff options
author | dfr <dfr@FreeBSD.org> | 2008-05-07 13:39:42 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 2008-05-07 13:39:42 +0000 |
commit | 51b6601db456e699ea5d4843cbc7239ee92d9c13 (patch) | |
tree | 4dbb862199a916e3ffe75f1cb08703ec0e662ffc /crypto/heimdal/lib/hx509 | |
parent | 2565fa13487d5bfc858144e431e3dfd7ffa5200e (diff) | |
download | FreeBSD-src-51b6601db456e699ea5d4843cbc7239ee92d9c13.zip FreeBSD-src-51b6601db456e699ea5d4843cbc7239ee92d9c13.tar.gz |
Vendor import of Heimdal 1.1
Diffstat (limited to 'crypto/heimdal/lib/hx509')
146 files changed, 35990 insertions, 0 deletions
diff --git a/crypto/heimdal/lib/hx509/ChangeLog b/crypto/heimdal/lib/hx509/ChangeLog new file mode 100644 index 0000000..cb29cee --- /dev/null +++ b/crypto/heimdal/lib/hx509/ChangeLog @@ -0,0 +1,2641 @@ +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/crypto/heimdal/lib/hx509/Makefile.am b/crypto/heimdal/lib/hx509/Makefile.am new file mode 100644 index 0000000..3144a71 --- /dev/null +++ b/crypto/heimdal/lib/hx509/Makefile.am @@ -0,0 +1,388 @@ +# $Id: Makefile.am 22459 2008-01-15 21:46:20Z lha $ + +include $(top_srcdir)/Makefile.am.common + +lib_LTLIBRARIES = libhx509.la +libhx509_la_LDFLAGS = -version-info 3:0:0 + +BUILT_SOURCES = \ + $(gen_files_ocsp:.x=.c) \ + $(gen_files_pkcs10:.x=.c) \ + hx509_err.c \ + hx509_err.h + +gen_files_ocsp = \ + asn1_OCSPBasicOCSPResponse.x \ + asn1_OCSPCertID.x \ + asn1_OCSPCertStatus.x \ + asn1_OCSPInnerRequest.x \ + asn1_OCSPKeyHash.x \ + asn1_OCSPRequest.x \ + asn1_OCSPResponderID.x \ + asn1_OCSPResponse.x \ + asn1_OCSPResponseBytes.x \ + asn1_OCSPResponseData.x \ + asn1_OCSPResponseStatus.x \ + asn1_OCSPSignature.x \ + asn1_OCSPSingleResponse.x \ + asn1_OCSPTBSRequest.x \ + asn1_OCSPVersion.x \ + asn1_id_pkix_ocsp.x \ + asn1_id_pkix_ocsp_basic.x \ + asn1_id_pkix_ocsp_nonce.x + +gen_files_pkcs10 = \ + asn1_CertificationRequestInfo.x \ + asn1_CertificationRequest.x + +gen_files_crmf = \ + asn1_CRMFRDNSequence.x \ + asn1_CertReqMessages.x \ + asn1_CertReqMsg.x \ + asn1_CertRequest.x \ + asn1_CertTemplate.x \ + asn1_Controls.x \ + asn1_PBMParameter.x \ + asn1_PKMACValue.x \ + asn1_POPOPrivKey.x \ + asn1_POPOSigningKey.x \ + asn1_POPOSigningKeyInput.x \ + asn1_ProofOfPossession.x \ + asn1_SubsequentMessage.x + +dist_libhx509_la_SOURCES = \ + ca.c \ + cert.c \ + cms.c \ + collector.c \ + crypto.c \ + doxygen.c \ + error.c \ + env.c \ + file.c \ + hx509-private.h \ + hx509-protos.h \ + hx509.h \ + hx_locl.h \ + 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 + +libhx509_la_LIBADD = \ + $(LIB_com_err) \ + $(LIB_hcrypto) \ + $(top_builddir)/lib/asn1/libasn1.la \ + $(LIBADD_roken) \ + $(LIB_dlopen) + +if FRAMEWORK_SECURITY +libhx509_la_LDFLAGS += -framework Security -framework CoreFoundation +endif + +if versionscript +libhx509_la_LDFLAGS += $(LDFLAGS_VERSION_SCRIPT)$(srcdir)/version-script.map +endif +$(libhx509_la_OBJECTS): $(srcdir)/version-script.map + +libhx509_la_CPPFLAGS = -I$(srcdir)/ref $(INCLUDE_hcrypto) +nodist_libhx509_la_SOURCES = $(BUILT_SOURCES) + +$(gen_files_ocsp) ocsp_asn1.h: ocsp_asn1_files +$(gen_files_pkcs10) pkcs10_asn1.h: pkcs10_asn1_files +$(gen_files_crmf) crmf_asn1.h: crmf_asn1_files + +asn1_compile = ../asn1/asn1_compile$(EXEEXT) + +ocsp_asn1_files: $(asn1_compile) $(srcdir)/ocsp.asn1 + $(asn1_compile) --preserve-binary=OCSPTBSRequest --preserve-binary=OCSPResponseData $(srcdir)/ocsp.asn1 ocsp_asn1 || (rm -f ocsp_asn1_files ; exit 1) + +pkcs10_asn1_files: $(asn1_compile) $(srcdir)/pkcs10.asn1 + $(asn1_compile) --preserve-binary=CertificationRequestInfo $(srcdir)/pkcs10.asn1 pkcs10_asn1 || (rm -f pkcs10_asn1_files ; exit 1) + +crmf_asn1_files: $(asn1_compile) $(srcdir)/crmf.asn1 + $(asn1_compile) $(srcdir)/crmf.asn1 crmf_asn1 || (rm -f crmf_asn1_files ; exit 1) + +$(libhx509_la_OBJECTS): $(srcdir)/hx509-protos.h $(srcdir)/hx509-private.h + +$(srcdir)/hx509-protos.h: + cd $(srcdir) && perl ../../cf/make-proto.pl -R '^(_|^C)' -E HX509_LIB_FUNCTION -q -P comment -o hx509-protos.h $(dist_libhx509_la_SOURCES) || rm -f hx509-protos.h + +$(srcdir)/hx509-private.h: + cd $(srcdir) && perl ../../cf/make-proto.pl -q -P comment -p hx509-private.h $(dist_libhx509_la_SOURCES) || rm -f hx509-private.h + +dist_include_HEADERS = hx509.h hx509-protos.h +nodist_include_HEADERS = hx509_err.h + +SLC = $(top_builddir)/lib/sl/slc + +bin_PROGRAMS = hxtool + +hxtool-commands.c hxtool-commands.h: hxtool-commands.in $(SLC) + $(SLC) $(srcdir)/hxtool-commands.in + +dist_hxtool_SOURCES = hxtool.c +nodist_hxtool_SOURCES = hxtool-commands.c hxtool-commands.h + +$(hxtool_OBJECTS): hxtool-commands.h + +hxtool_CPPFLAGS = $(INCLUDE_hcrypto) +hxtool_LDADD = \ + libhx509.la \ + $(top_builddir)/lib/asn1/libasn1.la \ + $(LIB_hcrypto) \ + $(LIB_roken) \ + $(top_builddir)/lib/sl/libsl.la + +CLEANFILES = $(BUILT_SOURCES) \ + $(gen_files_ocsp) ocsp_asn1_files ocsp_asn1.h \ + $(gen_files_pkcs10) pkcs10_asn1_files pkcs10_asn1.h \ + $(gen_files_crmf) crmf_asn1_files crmf_asn1.h \ + $(TESTS) \ + hxtool-commands.c hxtool-commands.h *.tmp \ + request.out \ + out.pem out2.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 +test_soft_pkcs11_CPPFLAGS = -I$(srcdir)/ref + +TESTS = $(SCRIPT_TESTS) $(PROGRAM_TESTS) + +PROGRAM_TESTS = \ + test_name + +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 = sed -e 's,[@]srcdir[@],$(srcdir),g' \ + -e 's,[@]objdir[@],$(top_builddir)/lib/hx509,g' + +test_ca: test_ca.in Makefile + $(do_subst) < $(srcdir)/test_ca.in > test_ca.tmp + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + chmod +x test_query.tmp + mv test_query.tmp test_query + +EXTRA_DIST = \ + version-script.map \ + crmf.asn1 \ + data/bleichenbacher-bad.pem \ + hx509_err.et \ + hxtool-commands.in \ + ocsp.asn1 \ + pkcs10.asn1 \ + 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/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.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/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.combined.crt \ + data/test.crt \ + data/test.key \ + data/test.p12 \ + 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/crypto/heimdal/lib/hx509/Makefile.in b/crypto/heimdal/lib/hx509/Makefile.in new file mode 100644 index 0000000..b564a49 --- /dev/null +++ b/crypto/heimdal/lib/hx509/Makefile.in @@ -0,0 +1,1530 @@ +# Makefile.in generated by automake 1.10 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program 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. + +@SET_MAKE@ + +# $Id: Makefile.am 22459 2008-01-15 21:46:20Z lha $ + +# $Id: Makefile.am.common 10998 2002-05-19 18:35:37Z joda $ + +# $Id: Makefile.am.common 22488 2008-01-21 11:47:22Z lha $ + + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +DIST_COMMON = $(dist_include_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/Makefile.am.common \ + $(top_srcdir)/cf/Makefile.am.common ChangeLog TODO +@FRAMEWORK_SECURITY_TRUE@am__append_1 = -framework Security -framework CoreFoundation +@versionscript_TRUE@am__append_2 = $(LDFLAGS_VERSION_SCRIPT)$(srcdir)/version-script.map +bin_PROGRAMS = hxtool$(EXEEXT) +check_PROGRAMS = $(am__EXEEXT_1) test_soft_pkcs11$(EXEEXT) +TESTS = $(SCRIPT_TESTS) $(am__EXEEXT_1) +subdir = lib/hx509 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/cf/aix.m4 \ + $(top_srcdir)/cf/auth-modules.m4 $(top_srcdir)/cf/autobuild.m4 \ + $(top_srcdir)/cf/broken-getaddrinfo.m4 \ + $(top_srcdir)/cf/broken-glob.m4 \ + $(top_srcdir)/cf/broken-realloc.m4 \ + $(top_srcdir)/cf/broken-snprintf.m4 $(top_srcdir)/cf/broken.m4 \ + $(top_srcdir)/cf/broken2.m4 $(top_srcdir)/cf/c-attribute.m4 \ + $(top_srcdir)/cf/capabilities.m4 \ + $(top_srcdir)/cf/check-compile-et.m4 \ + $(top_srcdir)/cf/check-getpwnam_r-posix.m4 \ + $(top_srcdir)/cf/check-man.m4 \ + $(top_srcdir)/cf/check-netinet-ip-and-tcp.m4 \ + $(top_srcdir)/cf/check-type-extra.m4 \ + $(top_srcdir)/cf/check-var.m4 $(top_srcdir)/cf/check-x.m4 \ + $(top_srcdir)/cf/check-xau.m4 $(top_srcdir)/cf/crypto.m4 \ + $(top_srcdir)/cf/db.m4 $(top_srcdir)/cf/destdirs.m4 \ + $(top_srcdir)/cf/dlopen.m4 \ + $(top_srcdir)/cf/find-func-no-libs.m4 \ + $(top_srcdir)/cf/find-func-no-libs2.m4 \ + $(top_srcdir)/cf/find-func.m4 \ + $(top_srcdir)/cf/find-if-not-broken.m4 \ + $(top_srcdir)/cf/framework-security.m4 \ + $(top_srcdir)/cf/have-struct-field.m4 \ + $(top_srcdir)/cf/have-type.m4 $(top_srcdir)/cf/irix.m4 \ + $(top_srcdir)/cf/krb-bigendian.m4 \ + $(top_srcdir)/cf/krb-func-getlogin.m4 \ + $(top_srcdir)/cf/krb-ipv6.m4 $(top_srcdir)/cf/krb-prog-ln-s.m4 \ + $(top_srcdir)/cf/krb-readline.m4 \ + $(top_srcdir)/cf/krb-struct-spwd.m4 \ + $(top_srcdir)/cf/krb-struct-winsize.m4 \ + $(top_srcdir)/cf/largefile.m4 $(top_srcdir)/cf/mips-abi.m4 \ + $(top_srcdir)/cf/misc.m4 $(top_srcdir)/cf/need-proto.m4 \ + $(top_srcdir)/cf/osfc2.m4 $(top_srcdir)/cf/otp.m4 \ + $(top_srcdir)/cf/proto-compat.m4 $(top_srcdir)/cf/pthreads.m4 \ + $(top_srcdir)/cf/resolv.m4 $(top_srcdir)/cf/retsigtype.m4 \ + $(top_srcdir)/cf/roken-frag.m4 \ + $(top_srcdir)/cf/socket-wrapper.m4 $(top_srcdir)/cf/sunos.m4 \ + $(top_srcdir)/cf/telnet.m4 $(top_srcdir)/cf/test-package.m4 \ + $(top_srcdir)/cf/version-script.m4 $(top_srcdir)/cf/wflags.m4 \ + $(top_srcdir)/cf/win32.m4 $(top_srcdir)/cf/with-all.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/include/config.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ + "$(DESTDIR)$(includedir)" "$(DESTDIR)$(includedir)" +libLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(lib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libhx509_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +dist_libhx509_la_OBJECTS = libhx509_la-ca.lo libhx509_la-cert.lo \ + libhx509_la-cms.lo libhx509_la-collector.lo \ + libhx509_la-crypto.lo libhx509_la-doxygen.lo \ + libhx509_la-error.lo libhx509_la-env.lo libhx509_la-file.lo \ + libhx509_la-keyset.lo libhx509_la-ks_dir.lo \ + libhx509_la-ks_file.lo libhx509_la-ks_mem.lo \ + libhx509_la-ks_null.lo libhx509_la-ks_p11.lo \ + libhx509_la-ks_p12.lo libhx509_la-ks_keychain.lo \ + libhx509_la-lock.lo libhx509_la-name.lo libhx509_la-peer.lo \ + libhx509_la-print.lo libhx509_la-softp11.lo libhx509_la-req.lo \ + libhx509_la-revoke.lo +am__objects_1 = libhx509_la-asn1_OCSPBasicOCSPResponse.lo \ + libhx509_la-asn1_OCSPCertID.lo \ + libhx509_la-asn1_OCSPCertStatus.lo \ + libhx509_la-asn1_OCSPInnerRequest.lo \ + libhx509_la-asn1_OCSPKeyHash.lo \ + libhx509_la-asn1_OCSPRequest.lo \ + libhx509_la-asn1_OCSPResponderID.lo \ + libhx509_la-asn1_OCSPResponse.lo \ + libhx509_la-asn1_OCSPResponseBytes.lo \ + libhx509_la-asn1_OCSPResponseData.lo \ + libhx509_la-asn1_OCSPResponseStatus.lo \ + libhx509_la-asn1_OCSPSignature.lo \ + libhx509_la-asn1_OCSPSingleResponse.lo \ + libhx509_la-asn1_OCSPTBSRequest.lo \ + libhx509_la-asn1_OCSPVersion.lo \ + libhx509_la-asn1_id_pkix_ocsp.lo \ + libhx509_la-asn1_id_pkix_ocsp_basic.lo \ + libhx509_la-asn1_id_pkix_ocsp_nonce.lo +am__objects_2 = libhx509_la-asn1_CertificationRequestInfo.lo \ + libhx509_la-asn1_CertificationRequest.lo +am__objects_3 = $(am__objects_1) $(am__objects_2) \ + libhx509_la-hx509_err.lo +nodist_libhx509_la_OBJECTS = $(am__objects_3) +libhx509_la_OBJECTS = $(dist_libhx509_la_OBJECTS) \ + $(nodist_libhx509_la_OBJECTS) +libhx509_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libhx509_la_LDFLAGS) $(LDFLAGS) -o $@ +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +am__EXEEXT_1 = test_name$(EXEEXT) +PROGRAMS = $(bin_PROGRAMS) +dist_hxtool_OBJECTS = hxtool-hxtool.$(OBJEXT) +nodist_hxtool_OBJECTS = hxtool-hxtool-commands.$(OBJEXT) +hxtool_OBJECTS = $(dist_hxtool_OBJECTS) $(nodist_hxtool_OBJECTS) +hxtool_DEPENDENCIES = libhx509.la $(top_builddir)/lib/asn1/libasn1.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/sl/libsl.la +test_name_SOURCES = test_name.c +test_name_OBJECTS = test_name.$(OBJEXT) +test_name_LDADD = $(LDADD) +test_name_DEPENDENCIES = libhx509.la +test_soft_pkcs11_SOURCES = test_soft_pkcs11.c +test_soft_pkcs11_OBJECTS = \ + test_soft_pkcs11-test_soft_pkcs11.$(OBJEXT) +test_soft_pkcs11_DEPENDENCIES = libhx509.la +DEFAULT_INCLUDES = -I. -I$(top_builddir)/include@am__isrc@ +depcomp = +am__depfiles_maybe = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(dist_libhx509_la_SOURCES) $(nodist_libhx509_la_SOURCES) \ + $(dist_hxtool_SOURCES) $(nodist_hxtool_SOURCES) test_name.c \ + test_soft_pkcs11.c +DIST_SOURCES = $(dist_libhx509_la_SOURCES) $(dist_hxtool_SOURCES) \ + test_name.c test_soft_pkcs11.c +dist_includeHEADERS_INSTALL = $(INSTALL_HEADER) +nodist_includeHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(dist_include_HEADERS) $(nodist_include_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AIX_EXTRA_KAFS = @AIX_EXTRA_KAFS@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CANONICAL_HOST = @CANONICAL_HOST@ +CATMAN = @CATMAN@ +CATMANEXT = @CATMANEXT@ +CC = @CC@ +CFLAGS = @CFLAGS@ +COMPILE_ET = @COMPILE_ET@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DBLIB = @DBLIB@ +DEFS = @DEFS@ +DIR_com_err = @DIR_com_err@ +DIR_hcrypto = @DIR_hcrypto@ +DIR_hdbdir = @DIR_hdbdir@ +DIR_roken = @DIR_roken@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +GROFF = @GROFF@ +INCLUDES_roken = @INCLUDES_roken@ +INCLUDE_hcrypto = @INCLUDE_hcrypto@ +INCLUDE_hesiod = @INCLUDE_hesiod@ +INCLUDE_krb4 = @INCLUDE_krb4@ +INCLUDE_openldap = @INCLUDE_openldap@ +INCLUDE_readline = @INCLUDE_readline@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_VERSION_SCRIPT = @LDFLAGS_VERSION_SCRIPT@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_roken = @LIBADD_roken@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIB_AUTH_SUBDIRS = @LIB_AUTH_SUBDIRS@ +LIB_NDBM = @LIB_NDBM@ +LIB_XauFileName = @LIB_XauFileName@ +LIB_XauReadAuth = @LIB_XauReadAuth@ +LIB_XauWriteAuth = @LIB_XauWriteAuth@ +LIB_bswap16 = @LIB_bswap16@ +LIB_bswap32 = @LIB_bswap32@ +LIB_com_err = @LIB_com_err@ +LIB_com_err_a = @LIB_com_err_a@ +LIB_com_err_so = @LIB_com_err_so@ +LIB_crypt = @LIB_crypt@ +LIB_db_create = @LIB_db_create@ +LIB_dbm_firstkey = @LIB_dbm_firstkey@ +LIB_dbopen = @LIB_dbopen@ +LIB_dlopen = @LIB_dlopen@ +LIB_dn_expand = @LIB_dn_expand@ +LIB_door_create = @LIB_door_create@ +LIB_el_init = @LIB_el_init@ +LIB_freeaddrinfo = @LIB_freeaddrinfo@ +LIB_gai_strerror = @LIB_gai_strerror@ +LIB_getaddrinfo = @LIB_getaddrinfo@ +LIB_gethostbyname = @LIB_gethostbyname@ +LIB_gethostbyname2 = @LIB_gethostbyname2@ +LIB_getnameinfo = @LIB_getnameinfo@ +LIB_getpwnam_r = @LIB_getpwnam_r@ +LIB_getsockopt = @LIB_getsockopt@ +LIB_hcrypto = @LIB_hcrypto@ +LIB_hcrypto_a = @LIB_hcrypto_a@ +LIB_hcrypto_appl = @LIB_hcrypto_appl@ +LIB_hcrypto_so = @LIB_hcrypto_so@ +LIB_hesiod = @LIB_hesiod@ +LIB_hstrerror = @LIB_hstrerror@ +LIB_kdb = @LIB_kdb@ +LIB_krb4 = @LIB_krb4@ +LIB_loadquery = @LIB_loadquery@ +LIB_logout = @LIB_logout@ +LIB_logwtmp = @LIB_logwtmp@ +LIB_openldap = @LIB_openldap@ +LIB_openpty = @LIB_openpty@ +LIB_otp = @LIB_otp@ +LIB_pidfile = @LIB_pidfile@ +LIB_readline = @LIB_readline@ +LIB_res_ndestroy = @LIB_res_ndestroy@ +LIB_res_nsearch = @LIB_res_nsearch@ +LIB_res_search = @LIB_res_search@ +LIB_roken = @LIB_roken@ +LIB_security = @LIB_security@ +LIB_setsockopt = @LIB_setsockopt@ +LIB_socket = @LIB_socket@ +LIB_syslog = @LIB_syslog@ +LIB_tgetent = @LIB_tgetent@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NROFF = @NROFF@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ +PTHREADS_LIBS = @PTHREADS_LIBS@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +VERSIONING = @VERSIONING@ +VOID_RETSIGTYPE = @VOID_RETSIGTYPE@ +WFLAGS = @WFLAGS@ +WFLAGS_NOIMPLICITINT = @WFLAGS_NOIMPLICITINT@ +WFLAGS_NOUNUSED = @WFLAGS_NOUNUSED@ +XMKMF = @XMKMF@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dpagaix_cflags = @dpagaix_cflags@ +dpagaix_ldadd = @dpagaix_ldadd@ +dpagaix_ldflags = @dpagaix_ldflags@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUFFIXES = .et .h .x .z .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8 +AM_CPPFLAGS = -I$(top_builddir)/include $(INCLUDES_roken) +@do_roken_rename_TRUE@ROKEN_RENAME = -DROKEN_RENAME +AM_CFLAGS = $(WFLAGS) +CP = cp +buildinclude = $(top_builddir)/include +LIB_getattr = @LIB_getattr@ +LIB_getpwent_r = @LIB_getpwent_r@ +LIB_odm_initialize = @LIB_odm_initialize@ +LIB_setpcred = @LIB_setpcred@ +HESIODLIB = @HESIODLIB@ +HESIODINCLUDE = @HESIODINCLUDE@ +NROFF_MAN = groff -mandoc -Tascii +LIB_kafs = $(top_builddir)/lib/kafs/libkafs.la $(AIX_EXTRA_KAFS) +@KRB5_TRUE@LIB_krb5 = $(top_builddir)/lib/krb5/libkrb5.la \ +@KRB5_TRUE@ $(top_builddir)/lib/asn1/libasn1.la + +@KRB5_TRUE@LIB_gssapi = $(top_builddir)/lib/gssapi/libgssapi.la +@KRB5_TRUE@LIB_tsasl = $(top_builddir)/lib/tsasl/libtsasl.la +@DCE_TRUE@LIB_kdfs = $(top_builddir)/lib/kdfs/libkdfs.la +lib_LTLIBRARIES = libhx509.la +libhx509_la_LDFLAGS = -version-info 3:0:0 $(am__append_1) \ + $(am__append_2) +BUILT_SOURCES = \ + $(gen_files_ocsp:.x=.c) \ + $(gen_files_pkcs10:.x=.c) \ + hx509_err.c \ + hx509_err.h + +gen_files_ocsp = \ + asn1_OCSPBasicOCSPResponse.x \ + asn1_OCSPCertID.x \ + asn1_OCSPCertStatus.x \ + asn1_OCSPInnerRequest.x \ + asn1_OCSPKeyHash.x \ + asn1_OCSPRequest.x \ + asn1_OCSPResponderID.x \ + asn1_OCSPResponse.x \ + asn1_OCSPResponseBytes.x \ + asn1_OCSPResponseData.x \ + asn1_OCSPResponseStatus.x \ + asn1_OCSPSignature.x \ + asn1_OCSPSingleResponse.x \ + asn1_OCSPTBSRequest.x \ + asn1_OCSPVersion.x \ + asn1_id_pkix_ocsp.x \ + asn1_id_pkix_ocsp_basic.x \ + asn1_id_pkix_ocsp_nonce.x + +gen_files_pkcs10 = \ + asn1_CertificationRequestInfo.x \ + asn1_CertificationRequest.x + +gen_files_crmf = \ + asn1_CRMFRDNSequence.x \ + asn1_CertReqMessages.x \ + asn1_CertReqMsg.x \ + asn1_CertRequest.x \ + asn1_CertTemplate.x \ + asn1_Controls.x \ + asn1_PBMParameter.x \ + asn1_PKMACValue.x \ + asn1_POPOPrivKey.x \ + asn1_POPOSigningKey.x \ + asn1_POPOSigningKeyInput.x \ + asn1_ProofOfPossession.x \ + asn1_SubsequentMessage.x + +dist_libhx509_la_SOURCES = \ + ca.c \ + cert.c \ + cms.c \ + collector.c \ + crypto.c \ + doxygen.c \ + error.c \ + env.c \ + file.c \ + hx509-private.h \ + hx509-protos.h \ + hx509.h \ + hx_locl.h \ + 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 + +libhx509_la_LIBADD = \ + $(LIB_com_err) \ + $(LIB_hcrypto) \ + $(top_builddir)/lib/asn1/libasn1.la \ + $(LIBADD_roken) \ + $(LIB_dlopen) + +libhx509_la_CPPFLAGS = -I$(srcdir)/ref $(INCLUDE_hcrypto) +nodist_libhx509_la_SOURCES = $(BUILT_SOURCES) +asn1_compile = ../asn1/asn1_compile$(EXEEXT) +dist_include_HEADERS = hx509.h hx509-protos.h +nodist_include_HEADERS = hx509_err.h +SLC = $(top_builddir)/lib/sl/slc +dist_hxtool_SOURCES = hxtool.c +nodist_hxtool_SOURCES = hxtool-commands.c hxtool-commands.h +hxtool_CPPFLAGS = $(INCLUDE_hcrypto) +hxtool_LDADD = \ + libhx509.la \ + $(top_builddir)/lib/asn1/libasn1.la \ + $(LIB_hcrypto) \ + $(LIB_roken) \ + $(top_builddir)/lib/sl/libsl.la + +CLEANFILES = $(BUILT_SOURCES) \ + $(gen_files_ocsp) ocsp_asn1_files ocsp_asn1.h \ + $(gen_files_pkcs10) pkcs10_asn1_files pkcs10_asn1.h \ + $(gen_files_crmf) crmf_asn1_files crmf_asn1.h \ + $(TESTS) \ + hxtool-commands.c hxtool-commands.h *.tmp \ + request.out \ + out.pem out2.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 + + +# +# regression tests +# +check_SCRIPTS = $(SCRIPT_TESTS) +LDADD = libhx509.la +test_soft_pkcs11_LDADD = libhx509.la +test_soft_pkcs11_CPPFLAGS = -I$(srcdir)/ref +PROGRAM_TESTS = \ + test_name + +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 = sed -e 's,[@]srcdir[@],$(srcdir),g' \ + -e 's,[@]objdir[@],$(top_builddir)/lib/hx509,g' + +EXTRA_DIST = \ + version-script.map \ + crmf.asn1 \ + data/bleichenbacher-bad.pem \ + hx509_err.et \ + hxtool-commands.in \ + ocsp.asn1 \ + pkcs10.asn1 \ + 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/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.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/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.combined.crt \ + data/test.crt \ + data/test.key \ + data/test.p12 \ + 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 + +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .et .h .x .z .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8 .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.am.common $(top_srcdir)/cf/Makefile.am.common $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign --ignore-deps lib/hx509/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign --ignore-deps lib/hx509/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libhx509.la: $(libhx509_la_OBJECTS) $(libhx509_la_DEPENDENCIES) + $(libhx509_la_LINK) -rpath $(libdir) $(libhx509_la_OBJECTS) $(libhx509_la_LIBADD) $(LIBS) +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +hxtool$(EXEEXT): $(hxtool_OBJECTS) $(hxtool_DEPENDENCIES) + @rm -f hxtool$(EXEEXT) + $(LINK) $(hxtool_OBJECTS) $(hxtool_LDADD) $(LIBS) +test_name$(EXEEXT): $(test_name_OBJECTS) $(test_name_DEPENDENCIES) + @rm -f test_name$(EXEEXT) + $(LINK) $(test_name_OBJECTS) $(test_name_LDADD) $(LIBS) +test_soft_pkcs11$(EXEEXT): $(test_soft_pkcs11_OBJECTS) $(test_soft_pkcs11_DEPENDENCIES) + @rm -f test_soft_pkcs11$(EXEEXT) + $(LINK) $(test_soft_pkcs11_OBJECTS) $(test_soft_pkcs11_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(COMPILE) -c $< + +.c.obj: + $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: + $(LTCOMPILE) -c -o $@ $< + +libhx509_la-ca.lo: ca.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-ca.lo `test -f 'ca.c' || echo '$(srcdir)/'`ca.c + +libhx509_la-cert.lo: cert.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-cert.lo `test -f 'cert.c' || echo '$(srcdir)/'`cert.c + +libhx509_la-cms.lo: cms.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-cms.lo `test -f 'cms.c' || echo '$(srcdir)/'`cms.c + +libhx509_la-collector.lo: collector.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-collector.lo `test -f 'collector.c' || echo '$(srcdir)/'`collector.c + +libhx509_la-crypto.lo: crypto.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c + +libhx509_la-doxygen.lo: doxygen.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-doxygen.lo `test -f 'doxygen.c' || echo '$(srcdir)/'`doxygen.c + +libhx509_la-error.lo: error.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-error.lo `test -f 'error.c' || echo '$(srcdir)/'`error.c + +libhx509_la-env.lo: env.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-env.lo `test -f 'env.c' || echo '$(srcdir)/'`env.c + +libhx509_la-file.lo: file.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-file.lo `test -f 'file.c' || echo '$(srcdir)/'`file.c + +libhx509_la-keyset.lo: keyset.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-keyset.lo `test -f 'keyset.c' || echo '$(srcdir)/'`keyset.c + +libhx509_la-ks_dir.lo: ks_dir.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-ks_dir.lo `test -f 'ks_dir.c' || echo '$(srcdir)/'`ks_dir.c + +libhx509_la-ks_file.lo: ks_file.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-ks_file.lo `test -f 'ks_file.c' || echo '$(srcdir)/'`ks_file.c + +libhx509_la-ks_mem.lo: ks_mem.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-ks_mem.lo `test -f 'ks_mem.c' || echo '$(srcdir)/'`ks_mem.c + +libhx509_la-ks_null.lo: ks_null.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-ks_null.lo `test -f 'ks_null.c' || echo '$(srcdir)/'`ks_null.c + +libhx509_la-ks_p11.lo: ks_p11.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-ks_p11.lo `test -f 'ks_p11.c' || echo '$(srcdir)/'`ks_p11.c + +libhx509_la-ks_p12.lo: ks_p12.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-ks_p12.lo `test -f 'ks_p12.c' || echo '$(srcdir)/'`ks_p12.c + +libhx509_la-ks_keychain.lo: ks_keychain.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-ks_keychain.lo `test -f 'ks_keychain.c' || echo '$(srcdir)/'`ks_keychain.c + +libhx509_la-lock.lo: lock.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-lock.lo `test -f 'lock.c' || echo '$(srcdir)/'`lock.c + +libhx509_la-name.lo: name.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-name.lo `test -f 'name.c' || echo '$(srcdir)/'`name.c + +libhx509_la-peer.lo: peer.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-peer.lo `test -f 'peer.c' || echo '$(srcdir)/'`peer.c + +libhx509_la-print.lo: print.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-print.lo `test -f 'print.c' || echo '$(srcdir)/'`print.c + +libhx509_la-softp11.lo: softp11.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-softp11.lo `test -f 'softp11.c' || echo '$(srcdir)/'`softp11.c + +libhx509_la-req.lo: req.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-req.lo `test -f 'req.c' || echo '$(srcdir)/'`req.c + +libhx509_la-revoke.lo: revoke.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-revoke.lo `test -f 'revoke.c' || echo '$(srcdir)/'`revoke.c + +libhx509_la-asn1_OCSPBasicOCSPResponse.lo: asn1_OCSPBasicOCSPResponse.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-asn1_OCSPBasicOCSPResponse.lo `test -f 'asn1_OCSPBasicOCSPResponse.c' || echo '$(srcdir)/'`asn1_OCSPBasicOCSPResponse.c + +libhx509_la-asn1_OCSPCertID.lo: asn1_OCSPCertID.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-asn1_OCSPCertID.lo `test -f 'asn1_OCSPCertID.c' || echo '$(srcdir)/'`asn1_OCSPCertID.c + +libhx509_la-asn1_OCSPCertStatus.lo: asn1_OCSPCertStatus.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-asn1_OCSPCertStatus.lo `test -f 'asn1_OCSPCertStatus.c' || echo '$(srcdir)/'`asn1_OCSPCertStatus.c + +libhx509_la-asn1_OCSPInnerRequest.lo: asn1_OCSPInnerRequest.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-asn1_OCSPInnerRequest.lo `test -f 'asn1_OCSPInnerRequest.c' || echo '$(srcdir)/'`asn1_OCSPInnerRequest.c + +libhx509_la-asn1_OCSPKeyHash.lo: asn1_OCSPKeyHash.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-asn1_OCSPKeyHash.lo `test -f 'asn1_OCSPKeyHash.c' || echo '$(srcdir)/'`asn1_OCSPKeyHash.c + +libhx509_la-asn1_OCSPRequest.lo: asn1_OCSPRequest.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-asn1_OCSPRequest.lo `test -f 'asn1_OCSPRequest.c' || echo '$(srcdir)/'`asn1_OCSPRequest.c + +libhx509_la-asn1_OCSPResponderID.lo: asn1_OCSPResponderID.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-asn1_OCSPResponderID.lo `test -f 'asn1_OCSPResponderID.c' || echo '$(srcdir)/'`asn1_OCSPResponderID.c + +libhx509_la-asn1_OCSPResponse.lo: asn1_OCSPResponse.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-asn1_OCSPResponse.lo `test -f 'asn1_OCSPResponse.c' || echo '$(srcdir)/'`asn1_OCSPResponse.c + +libhx509_la-asn1_OCSPResponseBytes.lo: asn1_OCSPResponseBytes.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-asn1_OCSPResponseBytes.lo `test -f 'asn1_OCSPResponseBytes.c' || echo '$(srcdir)/'`asn1_OCSPResponseBytes.c + +libhx509_la-asn1_OCSPResponseData.lo: asn1_OCSPResponseData.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-asn1_OCSPResponseData.lo `test -f 'asn1_OCSPResponseData.c' || echo '$(srcdir)/'`asn1_OCSPResponseData.c + +libhx509_la-asn1_OCSPResponseStatus.lo: asn1_OCSPResponseStatus.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-asn1_OCSPResponseStatus.lo `test -f 'asn1_OCSPResponseStatus.c' || echo '$(srcdir)/'`asn1_OCSPResponseStatus.c + +libhx509_la-asn1_OCSPSignature.lo: asn1_OCSPSignature.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-asn1_OCSPSignature.lo `test -f 'asn1_OCSPSignature.c' || echo '$(srcdir)/'`asn1_OCSPSignature.c + +libhx509_la-asn1_OCSPSingleResponse.lo: asn1_OCSPSingleResponse.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-asn1_OCSPSingleResponse.lo `test -f 'asn1_OCSPSingleResponse.c' || echo '$(srcdir)/'`asn1_OCSPSingleResponse.c + +libhx509_la-asn1_OCSPTBSRequest.lo: asn1_OCSPTBSRequest.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-asn1_OCSPTBSRequest.lo `test -f 'asn1_OCSPTBSRequest.c' || echo '$(srcdir)/'`asn1_OCSPTBSRequest.c + +libhx509_la-asn1_OCSPVersion.lo: asn1_OCSPVersion.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-asn1_OCSPVersion.lo `test -f 'asn1_OCSPVersion.c' || echo '$(srcdir)/'`asn1_OCSPVersion.c + +libhx509_la-asn1_id_pkix_ocsp.lo: asn1_id_pkix_ocsp.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-asn1_id_pkix_ocsp.lo `test -f 'asn1_id_pkix_ocsp.c' || echo '$(srcdir)/'`asn1_id_pkix_ocsp.c + +libhx509_la-asn1_id_pkix_ocsp_basic.lo: asn1_id_pkix_ocsp_basic.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-asn1_id_pkix_ocsp_basic.lo `test -f 'asn1_id_pkix_ocsp_basic.c' || echo '$(srcdir)/'`asn1_id_pkix_ocsp_basic.c + +libhx509_la-asn1_id_pkix_ocsp_nonce.lo: asn1_id_pkix_ocsp_nonce.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-asn1_id_pkix_ocsp_nonce.lo `test -f 'asn1_id_pkix_ocsp_nonce.c' || echo '$(srcdir)/'`asn1_id_pkix_ocsp_nonce.c + +libhx509_la-asn1_CertificationRequestInfo.lo: asn1_CertificationRequestInfo.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-asn1_CertificationRequestInfo.lo `test -f 'asn1_CertificationRequestInfo.c' || echo '$(srcdir)/'`asn1_CertificationRequestInfo.c + +libhx509_la-asn1_CertificationRequest.lo: asn1_CertificationRequest.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-asn1_CertificationRequest.lo `test -f 'asn1_CertificationRequest.c' || echo '$(srcdir)/'`asn1_CertificationRequest.c + +libhx509_la-hx509_err.lo: hx509_err.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhx509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhx509_la-hx509_err.lo `test -f 'hx509_err.c' || echo '$(srcdir)/'`hx509_err.c + +hxtool-hxtool.o: hxtool.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hxtool_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hxtool-hxtool.o `test -f 'hxtool.c' || echo '$(srcdir)/'`hxtool.c + +hxtool-hxtool.obj: hxtool.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hxtool_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hxtool-hxtool.obj `if test -f 'hxtool.c'; then $(CYGPATH_W) 'hxtool.c'; else $(CYGPATH_W) '$(srcdir)/hxtool.c'; fi` + +hxtool-hxtool-commands.o: hxtool-commands.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hxtool_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hxtool-hxtool-commands.o `test -f 'hxtool-commands.c' || echo '$(srcdir)/'`hxtool-commands.c + +hxtool-hxtool-commands.obj: hxtool-commands.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hxtool_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hxtool-hxtool-commands.obj `if test -f 'hxtool-commands.c'; then $(CYGPATH_W) 'hxtool-commands.c'; else $(CYGPATH_W) '$(srcdir)/hxtool-commands.c'; fi` + +test_soft_pkcs11-test_soft_pkcs11.o: test_soft_pkcs11.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_soft_pkcs11_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_soft_pkcs11-test_soft_pkcs11.o `test -f 'test_soft_pkcs11.c' || echo '$(srcdir)/'`test_soft_pkcs11.c + +test_soft_pkcs11-test_soft_pkcs11.obj: test_soft_pkcs11.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_soft_pkcs11_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_soft_pkcs11-test_soft_pkcs11.obj `if test -f 'test_soft_pkcs11.c'; then $(CYGPATH_W) 'test_soft_pkcs11.c'; else $(CYGPATH_W) '$(srcdir)/test_soft_pkcs11.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-dist_includeHEADERS: $(dist_include_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" + @list='$(dist_include_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(dist_includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \ + $(dist_includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \ + done + +uninstall-dist_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(dist_include_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \ + rm -f "$(DESTDIR)$(includedir)/$$f"; \ + done +install-nodist_includeHEADERS: $(nodist_include_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" + @list='$(nodist_include_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(nodist_includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \ + $(nodist_includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \ + done + +uninstall-nodist_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_include_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \ + rm -f "$(DESTDIR)$(includedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; ws='[ ]'; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *$$ws$$tst$$ws*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *$$ws$$tst$$ws*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(check_SCRIPTS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS check-local +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS) all-local +install-binPROGRAMS: install-libLTLIBRARIES + +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(includedir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ + clean-libLTLIBRARIES clean-libtool clean-local mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-dist_includeHEADERS \ + install-nodist_includeHEADERS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-data-hook + +install-dvi: install-dvi-am + +install-exec-am: install-binPROGRAMS install-libLTLIBRARIES + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-dist_includeHEADERS \ + uninstall-libLTLIBRARIES uninstall-nodist_includeHEADERS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-hook + +.MAKE: install-am install-data-am install-exec-am install-strip \ + uninstall-am + +.PHONY: CTAGS GTAGS all all-am all-local check check-TESTS check-am \ + check-local clean clean-binPROGRAMS clean-checkPROGRAMS \ + clean-generic clean-libLTLIBRARIES clean-libtool clean-local \ + ctags dist-hook distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-data-hook \ + install-dist_includeHEADERS install-dvi install-dvi-am \ + install-exec install-exec-am install-exec-hook install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man \ + install-nodist_includeHEADERS install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS \ + uninstall-dist_includeHEADERS uninstall-hook \ + uninstall-libLTLIBRARIES uninstall-nodist_includeHEADERS + + +install-suid-programs: + @foo='$(bin_SUIDS)'; \ + for file in $$foo; do \ + x=$(DESTDIR)$(bindir)/$$file; \ + if chown 0:0 $$x && chmod u+s $$x; then :; else \ + echo "*"; \ + echo "* Failed to install $$x setuid root"; \ + echo "*"; \ + fi; done + +install-exec-hook: install-suid-programs + +install-build-headers:: $(include_HEADERS) $(dist_include_HEADERS) $(nodist_include_HEADERS) $(build_HEADERZ) $(nobase_include_HEADERS) + @foo='$(include_HEADERS) $(dist_include_HEADERS) $(nodist_include_HEADERS) $(build_HEADERZ)'; \ + for f in $$foo; do \ + f=`basename $$f`; \ + if test -f "$(srcdir)/$$f"; then file="$(srcdir)/$$f"; \ + else file="$$f"; fi; \ + if cmp -s $$file $(buildinclude)/$$f 2> /dev/null ; then \ + : ; else \ + echo " $(CP) $$file $(buildinclude)/$$f"; \ + $(CP) $$file $(buildinclude)/$$f; \ + fi ; \ + done ; \ + foo='$(nobase_include_HEADERS)'; \ + for f in $$foo; do \ + if test -f "$(srcdir)/$$f"; then file="$(srcdir)/$$f"; \ + else file="$$f"; fi; \ + $(mkdir_p) $(buildinclude)/`dirname $$f` ; \ + if cmp -s $$file $(buildinclude)/$$f 2> /dev/null ; then \ + : ; else \ + echo " $(CP) $$file $(buildinclude)/$$f"; \ + $(CP) $$file $(buildinclude)/$$f; \ + fi ; \ + done + +all-local: install-build-headers + +check-local:: + @if test '$(CHECK_LOCAL)' = "no-check-local"; then \ + foo=''; elif test '$(CHECK_LOCAL)'; then \ + foo='$(CHECK_LOCAL)'; else \ + foo='$(PROGRAMS)'; fi; \ + if test "$$foo"; then \ + failed=0; all=0; \ + for i in $$foo; do \ + all=`expr $$all + 1`; \ + if (./$$i --version && ./$$i --help) > /dev/null 2>&1; then \ + echo "PASS: $$i"; \ + else \ + echo "FAIL: $$i"; \ + failed=`expr $$failed + 1`; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="$$failed of $$all tests failed"; \ + fi; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0 || exit 1; \ + fi + +.x.c: + @cmp -s $< $@ 2> /dev/null || cp $< $@ +#NROFF_MAN = nroff -man +.1.cat1: + $(NROFF_MAN) $< > $@ +.3.cat3: + $(NROFF_MAN) $< > $@ +.5.cat5: + $(NROFF_MAN) $< > $@ +.8.cat8: + $(NROFF_MAN) $< > $@ + +dist-cat1-mans: + @foo='$(man1_MANS)'; \ + bar='$(man_MANS)'; \ + for i in $$bar; do \ + case $$i in \ + *.1) foo="$$foo $$i";; \ + esac; done ;\ + for i in $$foo; do \ + x=`echo $$i | sed 's/\.[^.]*$$/.cat1/'`; \ + echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \ + $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \ + done + +dist-cat3-mans: + @foo='$(man3_MANS)'; \ + bar='$(man_MANS)'; \ + for i in $$bar; do \ + case $$i in \ + *.3) foo="$$foo $$i";; \ + esac; done ;\ + for i in $$foo; do \ + x=`echo $$i | sed 's/\.[^.]*$$/.cat3/'`; \ + echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \ + $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \ + done + +dist-cat5-mans: + @foo='$(man5_MANS)'; \ + bar='$(man_MANS)'; \ + for i in $$bar; do \ + case $$i in \ + *.5) foo="$$foo $$i";; \ + esac; done ;\ + for i in $$foo; do \ + x=`echo $$i | sed 's/\.[^.]*$$/.cat5/'`; \ + echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \ + $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \ + done + +dist-cat8-mans: + @foo='$(man8_MANS)'; \ + bar='$(man_MANS)'; \ + for i in $$bar; do \ + case $$i in \ + *.8) foo="$$foo $$i";; \ + esac; done ;\ + for i in $$foo; do \ + x=`echo $$i | sed 's/\.[^.]*$$/.cat8/'`; \ + echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \ + $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \ + done + +dist-hook: dist-cat1-mans dist-cat3-mans dist-cat5-mans dist-cat8-mans + +install-cat-mans: + $(SHELL) $(top_srcdir)/cf/install-catman.sh install "$(INSTALL_DATA)" "$(mkinstalldirs)" "$(srcdir)" "$(DESTDIR)$(mandir)" '$(CATMANEXT)' $(man_MANS) $(man1_MANS) $(man3_MANS) $(man5_MANS) $(man8_MANS) + +uninstall-cat-mans: + $(SHELL) $(top_srcdir)/cf/install-catman.sh uninstall "$(INSTALL_DATA)" "$(mkinstalldirs)" "$(srcdir)" "$(DESTDIR)$(mandir)" '$(CATMANEXT)' $(man_MANS) $(man1_MANS) $(man3_MANS) $(man5_MANS) $(man8_MANS) + +install-data-hook: install-cat-mans +uninstall-hook: uninstall-cat-mans + +.et.h: + $(COMPILE_ET) $< +.et.c: + $(COMPILE_ET) $< + +# +# Useful target for debugging +# + +check-valgrind: + tobjdir=`cd $(top_builddir) && pwd` ; \ + tsrcdir=`cd $(top_srcdir) && pwd` ; \ + env TESTS_ENVIRONMENT="$${tobjdir}/libtool --mode execute valgrind --leak-check=full --trace-children=yes --quiet -q --num-callers=30 --suppressions=$${tsrcdir}/cf/valgrind-suppressions" make check + +# +# Target to please samba build farm, builds distfiles in-tree. +# Will break when automake changes... +# + +distdir-in-tree: $(DISTFILES) $(INFO_DEPS) + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" != .; then \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) distdir-in-tree) ; \ + fi ; \ + done +$(libhx509_la_OBJECTS): $(srcdir)/version-script.map + +$(gen_files_ocsp) ocsp_asn1.h: ocsp_asn1_files +$(gen_files_pkcs10) pkcs10_asn1.h: pkcs10_asn1_files +$(gen_files_crmf) crmf_asn1.h: crmf_asn1_files + +ocsp_asn1_files: $(asn1_compile) $(srcdir)/ocsp.asn1 + $(asn1_compile) --preserve-binary=OCSPTBSRequest --preserve-binary=OCSPResponseData $(srcdir)/ocsp.asn1 ocsp_asn1 || (rm -f ocsp_asn1_files ; exit 1) + +pkcs10_asn1_files: $(asn1_compile) $(srcdir)/pkcs10.asn1 + $(asn1_compile) --preserve-binary=CertificationRequestInfo $(srcdir)/pkcs10.asn1 pkcs10_asn1 || (rm -f pkcs10_asn1_files ; exit 1) + +crmf_asn1_files: $(asn1_compile) $(srcdir)/crmf.asn1 + $(asn1_compile) $(srcdir)/crmf.asn1 crmf_asn1 || (rm -f crmf_asn1_files ; exit 1) + +$(libhx509_la_OBJECTS): $(srcdir)/hx509-protos.h $(srcdir)/hx509-private.h + +$(srcdir)/hx509-protos.h: + cd $(srcdir) && perl ../../cf/make-proto.pl -R '^(_|^C)' -E HX509_LIB_FUNCTION -q -P comment -o hx509-protos.h $(dist_libhx509_la_SOURCES) || rm -f hx509-protos.h + +$(srcdir)/hx509-private.h: + cd $(srcdir) && perl ../../cf/make-proto.pl -q -P comment -p hx509-private.h $(dist_libhx509_la_SOURCES) || rm -f hx509-private.h + +hxtool-commands.c hxtool-commands.h: hxtool-commands.in $(SLC) + $(SLC) $(srcdir)/hxtool-commands.in + +$(hxtool_OBJECTS): hxtool-commands.h + +clean-local: + @echo "cleaning PKITS" ; rm -rf PKITS_data + +test_ca: test_ca.in Makefile + $(do_subst) < $(srcdir)/test_ca.in > test_ca.tmp + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + chmod +x test_query.tmp + mv test_query.tmp test_query +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/crypto/heimdal/lib/hx509/ca.c b/crypto/heimdal/lib/hx509/ca.c new file mode 100644 index 0000000..4026070 --- /dev/null +++ b/crypto/heimdal/lib/hx509/ca.c @@ -0,0 +1,1518 @@ +/* + * 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" +#include <pkinit_asn1.h> +RCSID("$Id: ca.c 22456 2008-01-15 20:22:53Z lha $"); + +/** + * @page page_ca Hx509 CA functions + * + * See the library functions here: @ref hx509_ca + */ + +struct hx509_ca_tbs { + hx509_name subject; + SubjectPublicKeyInfo spki; + ExtKeyUsage eku; + GeneralNames san; + unsigned key_usage; + heim_integer serial; + struct { + unsigned int proxy:1; + unsigned int ca:1; + unsigned int key:1; + unsigned int serial:1; + unsigned int domaincontroller:1; + } flags; + time_t notBefore; + time_t notAfter; + int pathLenConstraint; /* both for CA and Proxy */ + CRLDistributionPoints crldp; +}; + +/** + * 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 + */ + +int +hx509_ca_tbs_init(hx509_context context, hx509_ca_tbs *tbs) +{ + *tbs = calloc(1, sizeof(**tbs)); + if (*tbs == NULL) + return ENOMEM; + + (*tbs)->subject = NULL; + (*tbs)->san.len = 0; + (*tbs)->san.val = NULL; + (*tbs)->eku.len = 0; + (*tbs)->eku.val = NULL; + (*tbs)->pathLenConstraint = 0; + (*tbs)->crldp.len = 0; + (*tbs)->crldp.val = NULL; + + return 0; +} + +/** + * Free an To Be Signed object. + * + * @param tbs object to free. + * + * @ingroup hx509_ca + */ + +void +hx509_ca_tbs_free(hx509_ca_tbs *tbs) +{ + if (tbs == NULL || *tbs == NULL) + return; + + free_SubjectPublicKeyInfo(&(*tbs)->spki); + free_GeneralNames(&(*tbs)->san); + free_ExtKeyUsage(&(*tbs)->eku); + der_free_heim_integer(&(*tbs)->serial); + free_CRLDistributionPoints(&(*tbs)->crldp); + + hx509_name_free(&(*tbs)->subject); + + 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 + */ + +int +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 + */ + +int +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 + */ + +int +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); +} + +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 }, + { 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 + */ + +const struct units * +hx509_ca_tbs_template_units(void) +{ + return templatebits; +} + +/** + * Initialize the to-be-signed certificate object from a template certifiate. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param flags bit field selecting what to copy from the template + * certifiate. + * @param cert template certificate. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +int +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) { + KeyUsage ku; + ret = _hx509_cert_get_keyusage(context, cert, &ku); + if (ret) + return ret; + tbs->key_usage = KeyUsage2int(ku); + } + if (flags & HX509_CA_TEMPLATE_EKU) { + ExtKeyUsage eku; + int 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); + } + 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 + */ + +int +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 + */ + +int +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 + */ + +int +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 + */ + +int +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 + */ + +int +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; +} + +/** + * 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 + */ + +int +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 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 + */ + +int +hx509_ca_tbs_add_crl_dp_uri(hx509_context context, + hx509_ca_tbs tbs, + const char *uri, + hx509_name issuername) +{ + DistributionPoint dp; + int ret; + + memset(&dp, 0, sizeof(dp)); + + dp.distributionPoint = ecalloc(1, sizeof(*dp.distributionPoint)); + + { + DistributionPointName name; + GeneralName gn; + size_t size; + + name.element = choice_DistributionPointName_fullName; + name.u.fullName.len = 1; + name.u.fullName.val = &gn; + + gn.element = choice_GeneralName_uniformResourceIdentifier; + gn.u.uniformResourceIdentifier = rk_UNCONST(uri); + + ASN1_MALLOC_ENCODE(DistributionPointName, + dp.distributionPoint->data, + dp.distributionPoint->length, + &name, &size, ret); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to encoded DistributionPointName"); + goto out; + } + if (dp.distributionPoint->length != size) + _hx509_abort("internal ASN.1 encoder error"); + } + + if (issuername) { +#if 1 + /** + * issuername not supported + */ + hx509_set_error_string(context, 0, EINVAL, + "CRLDistributionPoints.name.issuername not yet supported"); + return EINVAL; +#else + GeneralNames *crlissuer; + GeneralName gn; + Name n; + + crlissuer = calloc(1, sizeof(*crlissuer)); + if (crlissuer == NULL) { + return ENOMEM; + } + memset(&gn, 0, sizeof(gn)); + + gn.element = choice_GeneralName_directoryName; + ret = hx509_name_to_Name(issuername, &n); + if (ret) { + hx509_set_error_string(context, 0, ret, "out of memory"); + goto out; + } + + gn.u.directoryName.element = n.element; + gn.u.directoryName.u.rdnSequence = n.u.rdnSequence; + + ret = add_GeneralNames(&crlissuer, &gn); + free_Name(&n); + if (ret) { + hx509_set_error_string(context, 0, ret, "out of memory"); + goto out; + } + + dp.cRLIssuer = &crlissuer; +#endif + } + + ret = add_CRLDistributionPoints(&tbs->crldp, &dp); + if (ret) { + hx509_set_error_string(context, 0, ret, "out of memory"); + goto out; + } + +out: + free_DistributionPoint(&dp); + + 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 + */ + +int +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); +} + +/** + * 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 + */ + +int +hx509_ca_tbs_add_san_pkinit(hx509_context context, + hx509_ca_tbs tbs, + const char *principal) +{ + heim_octet_string os; + KRB5PrincipalName p; + size_t size; + int ret; + char *s = NULL; + + memset(&p, 0, sizeof(p)); + + /* parse principal */ + { + const char *str; + char *q; + int n; + + /* count number of component */ + n = 1; + for(str = principal; *str != '\0' && *str != '@'; str++){ + if(*str=='\\'){ + if(str[1] == '\0' || str[1] == '@') { + ret = HX509_PARSING_NAME_FAILED; + hx509_set_error_string(context, 0, ret, + "trailing \\ in principal name"); + goto out; + } + str++; + } else if(*str == '/') + n++; + } + 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; + q = s = strdup(principal); + if (q == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "malloc: out of memory"); + goto out; + } + p.realm = strrchr(q, '@'); + if (p.realm == NULL) { + ret = HX509_PARSING_NAME_FAILED; + hx509_set_error_string(context, 0, ret, "Missing @ in principal"); + goto out; + }; + *p.realm++ = '\0'; + + n = 0; + while (q) { + p.principalName.name_string.val[n++] = q; + q = strchr(q, '/'); + if (q) + *q++ = '\0'; + } + } + + 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"); + + ret = hx509_ca_tbs_add_san_otherName(context, + tbs, + oid_id_pkinit_san(), + &os); + free(os.data); +out: + if (p.principalName.name_string.val) + free (p.principalName.name_string.val); + if (s) + free(s); + 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)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"); + goto out; + } + 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); +out: + 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 + */ + +int +hx509_ca_tbs_add_san_ms_upn(hx509_context context, + hx509_ca_tbs tbs, + const char *principal) +{ + return add_utf8_san(context, tbs, 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 + */ + +int +hx509_ca_tbs_add_san_jid(hx509_context context, + hx509_ca_tbs tbs, + const char *jid) +{ + return add_utf8_san(context, tbs, 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 + */ + +int +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 = rk_UNCONST(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 + */ + +int +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 = rk_UNCONST(rfc822Name); + + return add_GeneralNames(&tbs->san, &gn); +} + +/** + * 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 + */ + +int +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); +} + +/** + * 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 enviroment 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 + */ + +int +hx509_ca_tbs_subject_expand(hx509_context context, + hx509_ca_tbs tbs, + hx509_env env) +{ + return hx509_name_expand(context, tbs->subject, env); +} + +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)); + + if (critical_flag) { + ext.critical = malloc(sizeof(*ext.critical)); + if (ext.critical == NULL) { + ret = ENOMEM; + hx509_set_error_string(context, 0, ret, "Out of memory"); + goto out; + } + *ext.critical = TRUE; + } + + 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); + asprintf(&tstr, "ts-%lu", (unsigned long)t); + if (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, 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_octet_string data; + Certificate c; + TBSCertificate *tbsc; + size_t size; + int ret; + const AlgorithmIdentifier *sigalg; + time_t notBefore; + time_t notAfter; + unsigned key_usage; + + 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; + + key_usage = tbs->key_usage; + if (key_usage == 0) { + KeyUsage ku; + memset(&ku, 0, sizeof(ku)); + ku.digitalSignature = 1; + ku.keyEncipherment = 1; + key_usage = KeyUsage2int(ku); + } + + if (tbs->flags.ca) { + KeyUsage ku; + memset(&ku, 0, sizeof(ku)); + ku.keyCertSign = 1; + ku.cRLSign = 1; + key_usage |= KeyUsage2int(ku); + } + + /* + * + */ + + tbsc = &c.tbsCertificate; + + 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 (tbs->subject == NULL) { + hx509_set_error_string(context, 0, EINVAL, "No subject name set"); + return EINVAL; + } + if (hx509_name_is_null_p(tbs->subject) && tbs->san.len == 0) { + hx509_set_error_string(context, 0, EINVAL, + "NULL 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 { + 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; + } + /* XXX diffrent */ + RAND_bytes(tbsc->serialNumber.data, tbsc->serialNumber.length); + ((unsigned char *)tbsc->serialNumber.data)[0] &= 0x7f; + } + /* signature AlgorithmIdentifier, */ + ret = copy_AlgorithmIdentifier(sigalg, &tbsc->signature); + if (ret) { + hx509_set_error_string(context, 0, ret, "Failed to copy sigature 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, */ + tbsc->validity.notBefore.element = choice_Time_generalTime; + tbsc->validity.notBefore.u.generalTime = notBefore; + 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 */ + /* subjectUniqueID [2] IMPLICIT BIT STRING OPTIONAL */ + /* 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, + oid_id_ms_cert_enroll_domaincontroller(), + &data); + if (ret) + goto out; + } + + /* add KeyUsage */ + { + KeyUsage ku; + + ku = int2KeyUsage(key_usage); + ASN1_MALLOC_ENCODE(KeyUsage, data.data, data.length, &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, + 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, 0, + 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"); + ret = add_extension(context, tbsc, 0, + 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, + 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]; + + { + SHA_CTX m; + + SHA1_Init(&m); + SHA1_Update(&m, tbs->spki.subjectPublicKey.data, + tbs->spki.subjectPublicKey.length / 8); + SHA1_Final (hash, &m); + } + + 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, + oid_id_x509_ce_subjectKeyIdentifier(), + &data); + free(data.data); + if (ret) + goto out; + } + + /* Add BasicConstraints */ + { + BasicConstraints bc; + int aCA = 1; + uint32_t path; + + memset(&bc, 0, sizeof(bc)); + + if (tbs->flags.ca) { + bc.cA = &aCA; + 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, + 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(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, + oid_id_pkix_pe_proxyCertInfo(), + &data); + free(data.data); + if (ret) + goto out; + } + + 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, + oid_id_x509_ce_cRLDistributionPoints(), + &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; + + ret = hx509_cert_init(context, &c, certificate); + if (ret) + 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 (ai->authorityCertSerialNumber == NULL) { + ret = ENOMEM; + 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_GeneralName_directoryName_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 + */ + +int +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 + */ + +int +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); +} diff --git a/crypto/heimdal/lib/hx509/cert.c b/crypto/heimdal/lib/hx509/cert.c new file mode 100644 index 0000000..1520e23 --- /dev/null +++ b/crypto/heimdal/lib/hx509/cert.c @@ -0,0 +1,3108 @@ +/* + * 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" +RCSID("$Id: cert.c 22450 2008-01-15 19:39:14Z lha $"); +#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 + 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; + +/** + * 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 + */ + +int +hx509_context_init(hx509_context *context) +{ + *context = calloc(1, sizeof(**context)); + if (*context == NULL) + return ENOMEM; + + _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); + + ENGINE_add_conf_module(); + OpenSSL_add_all_algorithms(); + + (*context)->ocsp_time_diff = HX509_DEFAULT_OCSP_TIME_DIFF; + + initialize_hx_error_table_r(&(*context)->et_list); + initialize_asn1_error_table_r(&(*context)->et_list); + +#ifdef HX509_DEFAULT_ANCHORS + (void)hx509_certs_init(*context, HX509_DEFAULT_ANCHORS, 0, + NULL, &(*context)->default_trust_anchors); +#endif + + return 0; +} + +/** + * Selects if the hx509_revoke_verify() function is going to require + * the existans of a revokation method (OSCP, 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 + */ + +void +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 + */ + +void +hx509_context_free(hx509_context *context) +{ + 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); + memset(*context, 0, sizeof(**context)); + free(*context); + *context = NULL; +} + +/* + * + */ + +Certificate * +_hx509_get_cert(hx509_cert cert) +{ + return cert->data; +} + +/* + * + */ + +int +_hx509_cert_get_version(const Certificate *t) +{ + return t->tbsCertificate.version ? *t->tbsCertificate.version + 1 : 1; +} + +/** + * Allocate and init an hx509 certificate object from the decoded + * certificate `c´. + * + * @param context A hx509 context. + * @param c + * @param cert + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_cert + */ + +int +hx509_cert_init(hx509_context context, const Certificate *c, hx509_cert *cert) +{ + int ret; + + *cert = malloc(sizeof(**cert)); + if (*cert == NULL) + return ENOMEM; + (*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 = calloc(1, sizeof(*(*cert)->data)); + if ((*cert)->data == NULL) { + free(*cert); + return ENOMEM; + } + ret = copy_Certificate(c, (*cert)->data); + if (ret) { + free((*cert)->data); + free(*cert); + *cert = NULL; + } + return ret; +} + +/** + * 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 cert a return pointer to a hx509 certificate object, will + * contain NULL on error. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +int +hx509_cert_init_data(hx509_context context, + const void *ptr, + size_t len, + hx509_cert *cert) +{ + Certificate t; + size_t size; + int ret; + + ret = decode_Certificate(ptr, len, &t, &size); + if (ret) { + hx509_set_error_string(context, 0, ret, "Failed to decode certificate"); + return ret; + } + if (size != len) { + hx509_set_error_string(context, 0, HX509_EXTRA_DATA_AFTER_STRUCTURE, + "Extra data after certificate"); + return HX509_EXTRA_DATA_AFTER_STRUCTURE; + } + + ret = hx509_cert_init(context, &t, cert); + free_Certificate(&t); + return ret; +} + +void +_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'. */ + +int +_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 + */ + +void +hx509_cert_free(hx509_cert cert) +{ + int 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); + + 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_cert +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 + */ + +int +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 + */ + +void +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). + * + * @param ctx a verification context + * @param set a keyset containing the trust anchors. + * + * @ingroup hx509_verify + */ + +void +hx509_verify_attach_anchors(hx509_verify_ctx ctx, hx509_certs set) +{ + 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 + */ + +void +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 + */ + +void +hx509_verify_set_time(hx509_verify_ctx ctx, time_t t) +{ + ctx->flags |= HX509_VERIFY_CTX_F_TIME_SET; + ctx->time_now = t; +} + +/** + * 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 + */ + +void +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 + */ + +void +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 + */ + +void +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 + */ + +void +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; +} + +static const Extension * +find_extension(const Certificate *cert, const heim_oid *oid, int *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; + int i = 0; + + memset(ai, 0, sizeof(*ai)); + + e = find_extension(subject, 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); +} + +int +_hx509_find_extension_subject_key_id(const Certificate *issuer, + SubjectKeyIdentifier *si) +{ + const Extension *e; + size_t size; + int i = 0; + + memset(si, 0, sizeof(*si)); + + e = find_extension(issuer, 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; + int i = 0; + + memset(nc, 0, sizeof(*nc)); + + e = find_extension(subject, 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, int *i, + GeneralNames *sa) +{ + const Extension *e; + size_t size; + + memset(sa, 0, sizeof(*sa)); + + e = find_extension(cert, 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; + int i = 0; + + memset(eku, 0, sizeof(*eku)); + + e = find_extension(cert, 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 + */ + +void +hx509_free_octet_string_list(hx509_octet_string_list *list) +{ + int i; + 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 + */ + +int +hx509_cert_find_subjectAltName_otherName(hx509_context context, + hx509_cert cert, + const heim_oid *oid, + hx509_octet_string_list *list) +{ + GeneralNames sa; + int ret, 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) { + ret = 0; + break; + } 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); + } + return 0; +} + + +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, i = 0; + unsigned ku_flags; + + if (_hx509_cert_get_version(cert) < 3) + return 0; + + e = find_extension(cert, 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 certifiate"); + 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) { + unsigned missing = (~ku_flags) & flags; + char buf[256], *name; + + 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 certifiate %s", buf, name); + 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 existance is required of the + * KeyUsage extension. + */ + +int +_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, int depth) +{ + BasicConstraints bc; + const Extension *e; + size_t size; + int ret, i = 0; + + if (_hx509_cert_get_version(cert) < 3) + return 0; + + e = find_extension(cert, 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 != NULL && *bc.cA) + ret = HX509_PARENT_IS_CA; + break; + case EE_CERT: + ret = 0; + break; + case CA_CERT: + if (bc.cA == NULL || !*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; +} + +int +_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; + + diff = _hx509_name_cmp(&issuer->tbsCertificate.subject, + &subject->tbsCertificate.issuer); + 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 = + ai.authorityCertIssuer->val[0].u.directoryName.element; + name.u.rdnSequence = + ai.authorityCertIssuer->val[0].u.directoryName.u.rdnSequence; + + diff = _hx509_name_cmp(&issuer->tbsCertificate.subject, + &name); + 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(const Certificate *cert) +{ + return _hx509_name_cmp(&cert->tbsCertificate.subject, + &cert->tbsCertificate.issuer) == 0; +} + +/* + * 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, i = 0; + + if (rinfo) + memset(rinfo, 0, sizeof(*rinfo)); + + e = find_extension(cert, 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. + */ + +int +_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; +} + +void +_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. + */ + +int +_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; +} + +int +_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; + } +} + +int +_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 + */ + +int +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 + */ + +int +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 + */ + +int +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 + */ + +int +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 have not been " + "canonicalize 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 + */ + +int +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 + */ + +time_t +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 + */ + +time_t +hx509_cert_get_notAfter(hx509_cert p) +{ + return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notAfter); +} + +/** + * 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 + */ + +int +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(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +int +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; +} + + +hx509_private_key +_hx509_cert_private_key(hx509_cert p) +{ + return p->private_key; +} + +int +hx509_cert_have_private_key(hx509_cert p) +{ + return p->private_key ? 1 : 0; +} + + +int +_hx509_cert_private_key_exportable(hx509_cert p) +{ + if (p->private_key == NULL) + return 0; + return _hx509_private_key_exportable(p->private_key); +} + +int +_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); +} + +int +_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); +} + +/* + * + */ + +time_t +_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) +{ + int i; + + if (c->len != n->len) + return HX509_NAME_CONSTRAINT_ERROR; + + for (i = 0; i < n->len; i++) { + if (der_heim_oid_cmp(&c->val[i].type, &n->val[i].type) != 0) + return HX509_NAME_CONSTRAINT_ERROR; + if (_hx509_name_ds_cmp(&c->val[i].value, &n->val[i].value) != 0) + return HX509_NAME_CONSTRAINT_ERROR; + } + return 0; +} + +static int +match_X501Name(const Name *c, const Name *n) +{ + int i, 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 = strchr(c->u.rfc822Name, '@'); + if (s) { + if (strcasecmp(c->u.rfc822Name, n->u.rfc822Name) != 0) + return HX509_NAME_CONSTRAINT_ERROR; + } else { + s = strchr(n->u.rfc822Name, '@'); + if (s == NULL) + return HX509_NAME_CONSTRAINT_ERROR; + len1 = strlen(c->u.rfc822Name); + len2 = strlen(s + 1); + if (len1 > len2) + return HX509_NAME_CONSTRAINT_ERROR; + if (strcasecmp(s + 1 + len2 - len1, c->u.rfc822Name) != 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; + + lenc = strlen(c->u.dNSName); + lenn = strlen(n->u.dNSName); + if (lenc > lenn) + return HX509_NAME_CONSTRAINT_ERROR; + if (strcasecmp(&n->u.dNSName[lenn - lenc], c->u.dNSName) != 0) + return HX509_NAME_CONSTRAINT_ERROR; + if (lenc != lenn && n->u.dNSName[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 = 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 = 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, 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; + ret = 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 = + c->tbsCertificate.subject.element; + certname.u.directoryName.u.rdnSequence = + c->tbsCertificate.subject.u.rdnSequence; + + ret = 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. + */ + ret = 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; + int 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 verify 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 verify constraints, " + "certificate included in excluded " + "subtree"); + return HX509_VERIFY_CONSTRAINTS; + } + } + } + return 0; +} + +static void +free_name_constraints(hx509_name_constraints *nc) +{ + int 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 + */ + +int +hx509_verify_path(hx509_context context, + hx509_verify_ctx ctx, + hx509_cert cert, + hx509_certs pool) +{ + hx509_name_constraints nc; + hx509_path path; +#if 0 + const AlgorithmIdentifier *alg_id; +#endif + int ret, i, proxy_cert_depth, selfsigned_depth; + enum certtype type; + Name proxy_issuer; + hx509_certs anchors = NULL; + + memset(&proxy_issuer, 0, sizeof(proxy_issuer)); + + 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; + +#if 0 + alg_id = path.val[path->len - 1]->data->tbsCertificate.signature; +#endif + + /* + * 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; + } + + if (i + 1 != path.len && certificate_is_self_signed(c)) + selfsigned_depth++; + + break; + case PROXY_CERT: { + ProxyCertInfo info; + + if (is_proxy_cert(context, c, &info) == 0) { + int 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 then allowed"); + goto out; + } + /* XXX MUST check info.proxyPolicy */ + free_ProxyCertInfo(&info); + + j = 0; + if (find_extension(c, oid_id_x509_ce_subjectAltName(), &j)) { + ret = HX509_PROXY_CERT_INVALID; + hx509_set_error_string(context, 0, ret, + "Proxy certificate have explicity " + "forbidden subjectAltName"); + goto out; + } + + j = 0; + if (find_extension(c, oid_id_x509_ce_issuerAltName(), &j)) { + ret = HX509_PROXY_CERT_INVALID; + hx509_set_error_string(context, 0, ret, + "Proxy certificate have explicity " + "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); + if (ret) { + 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, + 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); + if (ret != 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; + /* FALLTHOUGH */ + } + } + 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); + if (ret) { + 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, i = path.len - 1; i >= 0; i--) { + Certificate *c; + + c = _hx509_get_cert(path.val[i]); + + /* verify name constraints, not for selfsigned and anchor */ + if (!certificate_is_self_signed(c) || 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++) { + int 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 (i = path.len - 1; i >= 0; i--) { + Certificate *signer, *c; + + c = _hx509_get_cert(path.val[i]); + + /* is last in chain (trust anchor) */ + if (i + 1 == path.len) { + signer = path.val[i]->data; + + /* if trust anchor is not self signed, don't check sig */ + if (!certificate_is_self_signed(signer)) + continue; + } else { + /* take next certificate in chain */ + signer = path.val[i + 1]->data; + } + + /* 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; + } + } + +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 + */ + +int +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->data, alg, data, sig); +} + + +/** + * 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 + */ + +int +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; + int ret, i, j; + + 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) { + ret = 0; + break; + } else if (ret != 0) + break; + + for (j = 0; j < san.len; j++) { + switch (san.val[j].element) { + case choice_GeneralName_dNSName: + if (strcasecmp(san.val[j].u.dNSName, hostname) == 0) { + free_GeneralNames(&san); + return 0; + } + break; + default: + break; + } + } + free_GeneralNames(&san); + } while (1); + + { + Name *name = &cert->data->tbsCertificate.subject; + + /* match if first component is a CN= */ + if (name->u.rdnSequence.len > 0 + && name->u.rdnSequence.val[0].len == 1 + && der_heim_oid_cmp(&name->u.rdnSequence.val[0].val[0].type, + oid_id_at_commonName()) == 0) + { + DirectoryString *ds = &name->u.rdnSequence.val[0].val[0].value; + + switch (ds->element) { + case choice_DirectoryString_printableString: + if (strcasecmp(ds->u.printableString, hostname) == 0) + return 0; + break; + case choice_DirectoryString_ia5String: + if (strcasecmp(ds->u.ia5String, hostname) == 0) + return 0; + break; + case choice_DirectoryString_utf8String: + if (strcasecmp(ds->u.utf8String, hostname) == 0) + return 0; + default: + break; + } + } + } + + if ((flags & HX509_VHN_F_ALLOW_NO_MATCH) == 0) + ret = HX509_NAME_CONSTRAINT_ERROR; + + return ret; +} + +int +_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; + + 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; + + der_copy_octet_string(attr, &a->data); + der_copy_oid(oid, &a->oid); + + cert->attrs.val[cert->attrs.len] = a; + cert->attrs.len++; + + return 0; +} + +/** + * 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_cert_attribute +hx509_cert_get_attribute(hx509_cert cert, const heim_oid *oid) +{ + int 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 + */ + +int +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 + */ + +const char * +hx509_cert_get_friendly_name(hx509_cert cert) +{ + hx509_cert_attribute a; + PKCS9_friendlyName n; + size_t sz; + int ret, i; + + if (cert->friendlyname) + return cert->friendlyname; + + a = hx509_cert_get_attribute(cert, oid_id_pkcs_9_at_friendlyName()); + if (a == NULL) { + /* XXX use subject name ? */ + return NULL; + } + + 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; +} + +void +_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 + */ + +int +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 + */ + +void +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 + */ + +int +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 + */ + +int +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 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 + */ + +int +hx509_query_match_cmp_func(hx509_query *q, + int (*func)(void *, hx509_cert), + 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 + */ + +void +hx509_query_free(hx509_context context, hx509_query *q) +{ + if (q->serial) { + der_free_heim_integer(q->serial); + free(q->serial); + q->serial = NULL; + } + if (q->issuer_name) { + free_Name(q->issuer_name); + free(q->issuer_name); + q->issuer_name = NULL; + } + if (q) { + free(q->friendlyname); + memset(q, 0, sizeof(*q)); + } + free(q); +} + +int +_hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert cert) +{ + Certificate *c = _hx509_get_cert(cert); + + _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) + && _hx509_name_cmp(&c->tbsCertificate.issuer, q->issuer_name) != 0) + return 0; + + if ((q->match & HX509_QUERY_MATCH_SUBJECT_NAME) + && _hx509_name_cmp(&c->tbsCertificate.subject, q->subject_name) != 0) + return 0; + + if (q->match & HX509_QUERY_MATCH_SUBJECT_KEY_ID) { + SubjectKeyIdentifier si; + int ret; + + 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, 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) { + int ret = (*q->cmp_func)(q->cmp_func_ctx, cert); + if (ret != 0) + return 0; + } + + if (q->match & HX509_QUERY_MATCH_KEY_HASH_SHA1) { + heim_octet_string os; + int ret; + + 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 (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 + */ + +void +hx509_query_statistic_file(hx509_context context, const char *fn) +{ + if (context->querystat) + free(context->querystat); + context->querystat = strdup(fn); +} + +void +_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; + 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 + */ + +void +hx509_query_unparse_stats(hx509_context context, int printtype, FILE *out) +{ + rtbl_t t; + FILE *f; + int type, mask, i, num; + 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 statistic file %s: %s.\n", + context->querystat, strerror(errno)); + return; + } + + 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 + */ + +int +hx509_cert_check_eku(hx509_context context, hx509_cert cert, + const heim_oid *eku, int allow_any_eku) +{ + ExtKeyUsage e; + int ret, 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 0 + if (der_heim_oid_cmp(id_any_eku, &e.val[i]) == 0) { + free_ExtKeyUsage(&e); + return 0; + } +#endif + } + } + free_ExtKeyUsage(&e); + hx509_clear_error_string(context); + return HX509_CERTIFICATE_MISSING_EKU; +} + +int +_hx509_cert_get_keyusage(hx509_context context, + hx509_cert c, + KeyUsage *ku) +{ + Certificate *cert; + const Extension *e; + size_t size; + int ret, 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, 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; +} + +int +_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 returned structure with hx509_xfree(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +int +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) + +void +_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 + */ + +void +hx509_xfree(void *ptr) +{ + free(ptr); +} diff --git a/crypto/heimdal/lib/hx509/cms.c b/crypto/heimdal/lib/hx509/cms.c new file mode 100644 index 0000000..80bcaac --- /dev/null +++ b/crypto/heimdal/lib/hx509/cms.c @@ -0,0 +1,1426 @@ +/* + * 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" +RCSID("$Id: cms.c 22327 2007-12-15 04:49:37Z lha $"); + +/** + * @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 + */ + +int +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 + */ + +int +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; + /* FALL THOUGH */ + 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; + + *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; + } + 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; + + asprintf(str, "certificate with id %s", keyid); + free(keyid); + break; + } + default: + asprintf(str, "certificate have unknown CMSidentifier type"); + break; + } + if (*str == NULL) + return ENOMEM; + return 0; +} + +static int +find_CMSIdentifier(hx509_context context, + CMSIdentifier *client, + hx509_certs certs, + 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; + 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 contentType output type oid, should be freed with der_free_oid(). + * @param content the data, free with der_free_octet_string(). + * + * @ingroup hx509_cms + */ + +int +hx509_cms_unenvelope(hx509_context context, + hx509_certs certs, + int flags, + const void *data, + size_t length, + const heim_octet_string *encryptedContent, + 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, i, matched = 0, findflags = 0; + + + 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, &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 (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, no flags today + * @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(). + * + * @ingroup hx509_cms + */ + +int +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; + EnvelopedData ed; + size_t size; + int ret; + + 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 = oid_id_aes_256_cbc(); + + 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; + + 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 paramaters " + "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]; + + ri->version = 0; + ret = fill_CMSIdentifier(cert, CMS_ID_SKI, &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, i; + + if (sd->certificates == NULL) + return 0; + + for (i = 0; i < sd->certificates->len; i++) { + hx509_cert c; + + ret = hx509_cert_init_data(context, + sd->certificates->val[i].data, + sd->certificates->val[i].length, + &c); + if (ret) + 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) +{ + int 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 version context + * @param data + * @param length length of the data that data point to. + * @param signedContent + * @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(). + * + * @ingroup hx509_cms + */ + +int +hx509_cms_verify_signed(hx509_context context, + hx509_verify_ctx ctx, + 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) +{ + SignerInfo *signer_info; + hx509_cert cert = NULL; + hx509_certs certs = NULL; + SignedData sd; + size_t size; + int ret, i, found_valid_sig; + + *signer_certs = NULL; + 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) + signedContent = sd.encapContentInfo.eContent; + + 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; + 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, &cert, + HX509_QUERY_KU_DIGITALSIGNATURE); + 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, 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, + signedContent, + &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, oid_id_pkcs9_contentType()); + if (attr == NULL) { + match_oid = 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; + } + + ALLOC(signed_data, 1); + if (signed_data == NULL) { + if (match_oid == &decode_oid) + der_free_oid(&decode_oid); + ret = ENOMEM; + hx509_clear_error_string(context); + goto next_sigature; + } + + 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); + free(signed_data); + hx509_clear_error_string(context); + goto next_sigature; + } + if (size != signed_data->length) + _hx509_abort("internal ASN.1 encoder error"); + + } else { + signed_data = rk_UNCONST(signedContent); + match_oid = oid_id_pkcs7_data(); + } + + if (der_heim_oid_cmp(match_oid, &sd.encapContentInfo.eContentType)) { + 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 sigature in " + "CMS SignedData"); + } + if (signed_data != signedContent) { + der_free_octet_string(signed_data); + free(signed_data); + } + if (ret) + goto next_sigature; + + ret = hx509_verify_path(context, ctx, cert, certs); + if (ret) + goto next_sigature; + + ret = hx509_certs_add(context, *signer_certs, cert); + if (ret) + goto next_sigature; + + found_valid_sig++; + + next_sigature: + if (cert) + hx509_cert_free(cert); + cert = NULL; + } + 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; + } + + content->data = malloc(signedContent->length); + if (content->data == NULL) { + hx509_clear_error_string(context); + ret = ENOMEM; + goto out; + } + content->length = signedContent->length; + memcpy(content->data, signedContent->data, content->length); + +out: + free_SignedData(&sd); + if (certs) + hx509_certs_free(&certs); + if (ret) { + 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(). + * + * @ingroup hx509_cms + */ + +int +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) +{ + AlgorithmIdentifier digest; + hx509_name name; + SignerInfo *signer_info; + heim_octet_string buf, content, sigdata = { 0, NULL }; + SignedData sd; + int ret; + size_t size; + hx509_path path; + int cmsidflag = CMS_ID_SKI; + + memset(&sd, 0, sizeof(sd)); + memset(&name, 0, sizeof(name)); + memset(&path, 0, sizeof(path)); + memset(&digest, 0, sizeof(digest)); + + content.data = rk_UNCONST(data); + content.length = length; + + if (flags & HX509_CMS_SIGATURE_ID_NAME) + cmsidflag = CMS_ID_NAME; + + 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 (digest_alg == NULL) { + ret = hx509_crypto_select(context, HX509_SELECT_DIGEST, + _hx509_cert_private_key(cert), peer, &digest); + } else { + ret = copy_AlgorithmIdentifier(digest_alg, &digest); + if (ret) + hx509_clear_error_string(context); + } + if (ret) + goto out; + + sd.version = CMSVersion_v3; + + if (eContentType == NULL) + eContentType = oid_id_pkcs7_data(); + + der_copy_oid(eContentType, &sd.encapContentInfo.eContentType); + + /* */ + if ((flags & HX509_CMS_SIGATURE_DETACHED) == 0) { + ALLOC(sd.encapContentInfo.eContent, 1); + if (sd.encapContentInfo.eContent == NULL) { + hx509_clear_error_string(context); + ret = ENOMEM; + goto out; + } + + sd.encapContentInfo.eContent->data = malloc(length); + if (sd.encapContentInfo.eContent->data == NULL) { + hx509_clear_error_string(context); + ret = ENOMEM; + goto out; + } + memcpy(sd.encapContentInfo.eContent->data, data, length); + sd.encapContentInfo.eContent->length = length; + } + + ALLOC_SEQ(&sd.signerInfos, 1); + if (sd.signerInfos.val == NULL) { + hx509_clear_error_string(context); + ret = ENOMEM; + goto out; + } + + signer_info = &sd.signerInfos.val[0]; + + signer_info->version = 1; + + ret = fill_CMSIdentifier(cert, 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(eContentType, 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, + &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, + oid_id_pkcs9_messageDigest(), + &buf); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + + + ASN1_MALLOC_ENCODE(ContentType, + buf.data, + buf.length, + 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, + oid_id_pkcs9_contentType(), + &buf); + if (ret) { + 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 = content.data; + sigdata.length = content.length; + } + + + { + AlgorithmIdentifier sigalg; + + ret = hx509_crypto_select(context, HX509_SELECT_PUBLIC_SIG, + _hx509_cert_private_key(cert), 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; + } + + ALLOC_SEQ(&sd.digestAlgorithms, 1); + if (sd.digestAlgorithms.val == NULL) { + ret = ENOMEM; + hx509_clear_error_string(context); + goto out; + } + + ret = copy_AlgorithmIdentifier(&digest, &sd.digestAlgorithms.val[0]); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + + /* + * Provide best effort path + */ + if (pool) { + _hx509_calculate_path(context, + HX509_CALCULATE_PATH_NO_ANCHOR, + time(NULL), + anchors, + 0, + cert, + pool, + &path); + } else + _hx509_path_append(context, &path, cert); + + + if (path.len) { + int i; + + ALLOC(sd.certificates, 1); + if (sd.certificates == NULL) { + hx509_clear_error_string(context); + ret = ENOMEM; + goto out; + } + ALLOC_SEQ(sd.certificates, path.len); + if (sd.certificates->val == NULL) { + hx509_clear_error_string(context); + ret = ENOMEM; + goto out; + } + + for (i = 0; i < path.len; i++) { + ret = hx509_cert_binary(context, path.val[i], + &sd.certificates->val[i]); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + } + } + + ASN1_MALLOC_ENCODE(SignedData, + signed_data->data, signed_data->length, + &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: + if (sigdata.data != content.data) + der_free_octet_string(&sigdata); + free_AlgorithmIdentifier(&digest); + _hx509_path_free(&path); + free_SignedData(&sd); + + return ret; +} + +int +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/crypto/heimdal/lib/hx509/collector.c b/crypto/heimdal/lib/hx509/collector.c new file mode 100644 index 0000000..8b6ffcb --- /dev/null +++ b/crypto/heimdal/lib/hx509/collector.c @@ -0,0 +1,329 @@ +/* + * 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" +RCSID("$Id: collector.c 20778 2007-06-01 22:04:13Z lha $"); + +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; +}; + + +int +_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_lock +_hx509_collector_get_lock(struct hx509_collector *c) +{ + return c->lock; +} + + +int +_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); +} + +int +_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->algorithm, + key_data->data, key_data->length, + &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) { + + 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; +} + +int +_hx509_collector_collect_certs(hx509_context context, + struct hx509_collector *c, + hx509_certs *ret_certs) +{ + hx509_certs certs; + int ret, 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; +} + +int +_hx509_collector_collect_private_keys(hx509_context context, + struct hx509_collector *c, + hx509_private_key **keys) +{ + int 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; +} + + +void +_hx509_collector_free(struct hx509_collector *c) +{ + int 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/crypto/heimdal/lib/hx509/crmf.asn1 b/crypto/heimdal/lib/hx509/crmf.asn1 new file mode 100644 index 0000000..97ade26 --- /dev/null +++ b/crypto/heimdal/lib/hx509/crmf.asn1 @@ -0,0 +1,113 @@ +-- $Id: crmf.asn1 17102 2006-04-18 13:05:21Z lha $ +PKCS10 DEFINITIONS ::= + +BEGIN + +IMPORTS + Time, + GeneralName, + SubjectPublicKeyInfo, + RelativeDistinguishedName, + AttributeTypeAndValue, + Extension, + AlgorithmIdentifier + FROM rfc2459 + heim_any + FROM heim; + +CRMFRDNSequence ::= SEQUENCE OF RelativeDistinguishedName + +Controls ::= SEQUENCE -- SIZE(1..MAX) -- OF AttributeTypeAndValue + +-- XXX IMPLICIT brokenness +POPOSigningKey ::= SEQUENCE { + poposkInput [0] IMPLICIT POPOSigningKeyInput OPTIONAL, + algorithmIdentifier AlgorithmIdentifier, + signature BIT STRING } + +PKMACValue ::= SEQUENCE { + algId AlgorithmIdentifier, + value BIT STRING +} + +-- XXX IMPLICIT brokenness +POPOSigningKeyInput ::= SEQUENCE { + authInfo CHOICE { + sender [0] IMPLICIT GeneralName, + publicKeyMAC PKMACValue + }, + publicKey SubjectPublicKeyInfo +} -- from CertTemplate + + +PBMParameter ::= SEQUENCE { + salt OCTET STRING, + owf AlgorithmIdentifier, + iterationCount INTEGER, + mac AlgorithmIdentifier +} + +SubsequentMessage ::= INTEGER { + encrCert (0), + challengeResp (1) +} + +-- XXX IMPLICIT brokenness +POPOPrivKey ::= CHOICE { + thisMessage [0] BIT STRING, -- Deprecated + subsequentMessage [1] IMPLICIT SubsequentMessage, + dhMAC [2] BIT STRING, -- Deprecated + agreeMAC [3] IMPLICIT PKMACValue, + encryptedKey [4] heim_any +} + +-- XXX IMPLICIT brokenness +ProofOfPossession ::= CHOICE { + raVerified [0] NULL, + signature [1] POPOSigningKey, + keyEncipherment [2] POPOPrivKey, + keyAgreement [3] POPOPrivKey +} + +CertTemplate ::= SEQUENCE { + version [0] INTEGER OPTIONAL, + serialNumber [1] INTEGER OPTIONAL, + signingAlg [2] SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters heim_any OPTIONAL + } -- AlgorithmIdentifier -- OPTIONAL, + issuer [3] IMPLICIT CHOICE { + rdnSequence CRMFRDNSequence + } -- Name -- OPTIONAL, + validity [4] SEQUENCE { + notBefore [0] Time OPTIONAL, + notAfter [1] Time OPTIONAL + } -- OptionalValidity -- OPTIONAL, + subject [5] IMPLICIT CHOICE { + rdnSequence CRMFRDNSequence + } -- Name -- OPTIONAL, + publicKey [6] IMPLICIT SEQUENCE { + algorithm AlgorithmIdentifier, + subjectPublicKey BIT STRING OPTIONAL + } -- SubjectPublicKeyInfo -- OPTIONAL, + issuerUID [7] IMPLICIT BIT STRING OPTIONAL, + subjectUID [8] IMPLICIT BIT STRING OPTIONAL, + extensions [9] IMPLICIT SEQUENCE OF Extension OPTIONAL +} + +CertRequest ::= SEQUENCE { + certReqId INTEGER, + certTemplate CertTemplate, + controls Controls OPTIONAL +} + +CertReqMsg ::= SEQUENCE { + certReq CertRequest, + popo ProofOfPossession OPTIONAL, + regInfo SEQUENCE OF AttributeTypeAndValue OPTIONAL } + +CertReqMessages ::= SEQUENCE OF CertReqMsg + + +END + diff --git a/crypto/heimdal/lib/hx509/crypto.c b/crypto/heimdal/lib/hx509/crypto.c new file mode 100644 index 0000000..e0f00ad --- /dev/null +++ b/crypto/heimdal/lib/hx509/crypto.c @@ -0,0 +1,2706 @@ +/* + * 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" +RCSID("$Id: crypto.c 22435 2008-01-14 20:53:56Z lha $"); + +struct hx509_crypto; + +struct signature_alg; + +enum crypto_op_type { + COT_SIGN +}; + +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)(void); + int (*get_spki)(hx509_context, + const hx509_private_key, + SubjectPublicKeyInfo *); + int (*export)(hx509_context context, + const hx509_private_key, + heim_octet_string *); + int (*import)(hx509_context, + const void *data, + size_t len, + hx509_private_key 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 *); + int (*handle_alg)(const hx509_private_key, + const AlgorithmIdentifier *, + enum crypto_op_type); + int (*sign)(hx509_context context, + const hx509_private_key, + const AlgorithmIdentifier *, + const heim_octet_string *, + AlgorithmIdentifier *, + heim_octet_string *); +#if 0 + const AlgorithmIdentifier *(*preferred_sig_alg) + (const hx509_private_key, + const hx509_peer_info); + int (*unwrap)(hx509_context context, + const hx509_private_key, + const AlgorithmIdentifier *, + const heim_octet_string *, + heim_octet_string *); +#endif +}; + +struct hx509_private_key { + unsigned int ref; + const struct signature_alg *md; + const heim_oid *signature_alg; + union { + RSA *rsa; + void *keydata; + } private_key; + /* new crypto layer */ + hx509_private_key_ops *ops; +}; + +/* + * + */ + +struct signature_alg { + const char *name; + const heim_oid *(*sig_oid)(void); + const AlgorithmIdentifier *(*sig_alg)(void); + const heim_oid *(*key_oid)(void); + const heim_oid *(*digest_oid)(void); + int flags; +#define PROVIDE_CONF 1 +#define REQUIRE_SIGNER 2 + +#define SIG_DIGEST 0x100 +#define SIG_PUBLIC_SIG 0x200 +#define SIG_SECRET 0x400 + +#define RA_RSA_USES_DIGEST_INFO 0x1000000 + + + 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 *); +}; + +/* + * + */ + +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; +} + +/* + * + */ + +static int +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; + RSAPublicKey pk; + size_t size; + + memset(&di, 0, sizeof(di)); + + spi = &signer->tbsCertificate.subjectPublicKeyInfo; + + rsa = RSA_new(); + if (rsa == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + ret = decode_RSAPublicKey(spi->subjectPublicKey.data, + spi->subjectPublicKey.length / 8, + &pk, &size); + if (ret) { + hx509_set_error_string(context, 0, ret, "Failed to decode RSAPublicKey"); + goto out; + } + + rsa->n = heim_int2BN(&pk.modulus); + rsa->e = heim_int2BN(&pk.publicExponent); + + free_RSAPublicKey(&pk); + + if (rsa->n == NULL || rsa->e == 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 != retsize) { + ret = HX509_CRYPTO_SIG_INVALID_FORMAT; + hx509_set_error_string(context, 0, ret, "size from decryption mismatch"); + goto out; + } + + if (sig_alg->digest_oid && + der_heim_oid_cmp(&di.digestAlgorithm.algorithm, + (*sig_alg->digest_oid)()) != 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); + } else { + if (retsize != data->length || + 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); + } + + out: + free_DigestInfo(&di); + 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 (alg) + sig_oid = &alg->algorithm; + else + sig_oid = signer->signature_alg; + + if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_sha256WithRSAEncryption()) == 0) { + digest_alg = hx509_signature_sha256(); + } else if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_sha1WithRSAEncryption()) == 0) { + digest_alg = hx509_signature_sha1(); + } else if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_md5WithRSAEncryption()) == 0) { + digest_alg = hx509_signature_md5(); + } else if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_md5WithRSAEncryption()) == 0) { + digest_alg = hx509_signature_md5(); + } else if (der_heim_oid_cmp(sig_oid, oid_id_dsa_with_sha1()) == 0) { + digest_alg = hx509_signature_sha1(); + } else if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_rsaEncryption()) == 0) { + digest_alg = hx509_signature_sha1(); + } else if (der_heim_oid_cmp(sig_oid, oid_id_heim_rsa_pkcs1_x509()) == 0) { + digest_alg = NULL; + } else + return HX509_ALG_NOT_SUPP; + + if (signatureAlgorithm) { + ret = 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 decrypt failed: %d", ret); + return ret; + } + if (ret > sig->length) + _hx509_abort("RSA signature prelen longer the output len"); + + sig->length = ret; + + return 0; +} + +static int +rsa_private_key_import(hx509_context context, + const void *data, + size_t len, + hx509_private_key private_key) +{ + 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 = oid_id_pkcs1_sha1WithRSAEncryption(); + + 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); + + 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 = set_digest_alg(&spki->algorithm,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 = 1024; + + 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; + else if (ctx->isCA) + bits *= 2; + + 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 = oid_id_pkcs1_sha1WithRSAEncryption(); + + return 0; +} + +static int +rsa_private_key_export(hx509_context context, + const hx509_private_key key, + heim_octet_string *data) +{ + int ret; + + data->data = NULL; + data->length = 0; + + 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); + } + + 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", + oid_id_pkcs1_rsaEncryption, + 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 = 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 +sha1_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[SHA_DIGEST_LENGTH]; + SHA_CTX m; + + if (sig->length != SHA_DIGEST_LENGTH) { + hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, + "SHA1 sigature have wrong length"); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + + SHA1_Init(&m); + SHA1_Update(&m, data->data, data->length); + SHA1_Final (digest, &m); + + if (memcmp(digest, sig->data, SHA_DIGEST_LENGTH) != 0) { + hx509_set_error_string(context, 0, HX509_CRYPTO_BAD_SIGNATURE, + "Bad SHA1 sigature"); + return HX509_CRYPTO_BAD_SIGNATURE; + } + + return 0; +} + +static int +sha256_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) +{ + SHA256_CTX m; + + memset(sig, 0, sizeof(*sig)); + + if (signatureAlgorithm) { + int ret; + ret = set_digest_alg(signatureAlgorithm, (*sig_alg->sig_oid)(), + "\x05\x00", 2); + if (ret) + return ret; + } + + + sig->data = malloc(SHA256_DIGEST_LENGTH); + if (sig->data == NULL) { + sig->length = 0; + return ENOMEM; + } + sig->length = SHA256_DIGEST_LENGTH; + + SHA256_Init(&m); + SHA256_Update(&m, data->data, data->length); + SHA256_Final (sig->data, &m); + + return 0; +} + +static int +sha256_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[SHA256_DIGEST_LENGTH]; + SHA256_CTX m; + + if (sig->length != SHA256_DIGEST_LENGTH) { + hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, + "SHA256 sigature have wrong length"); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + + SHA256_Init(&m); + SHA256_Update(&m, data->data, data->length); + SHA256_Final (digest, &m); + + if (memcmp(digest, sig->data, SHA256_DIGEST_LENGTH) != 0) { + hx509_set_error_string(context, 0, HX509_CRYPTO_BAD_SIGNATURE, + "Bad SHA256 sigature"); + return HX509_CRYPTO_BAD_SIGNATURE; + } + + return 0; +} + +static int +sha1_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) +{ + SHA_CTX m; + + memset(sig, 0, sizeof(*sig)); + + if (signatureAlgorithm) { + int ret; + ret = set_digest_alg(signatureAlgorithm, (*sig_alg->sig_oid)(), + "\x05\x00", 2); + if (ret) + return ret; + } + + + sig->data = malloc(SHA_DIGEST_LENGTH); + if (sig->data == NULL) { + sig->length = 0; + return ENOMEM; + } + sig->length = SHA_DIGEST_LENGTH; + + SHA1_Init(&m); + SHA1_Update(&m, data->data, data->length); + SHA1_Final (sig->data, &m); + + return 0; +} + +static int +md5_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[MD5_DIGEST_LENGTH]; + MD5_CTX m; + + if (sig->length != MD5_DIGEST_LENGTH) { + hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, + "MD5 sigature have wrong length"); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + + MD5_Init(&m); + MD5_Update(&m, data->data, data->length); + MD5_Final (digest, &m); + + if (memcmp(digest, sig->data, MD5_DIGEST_LENGTH) != 0) { + hx509_set_error_string(context, 0, HX509_CRYPTO_BAD_SIGNATURE, + "Bad MD5 sigature"); + return HX509_CRYPTO_BAD_SIGNATURE; + } + + return 0; +} + +static int +md2_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[MD2_DIGEST_LENGTH]; + MD2_CTX m; + + if (sig->length != MD2_DIGEST_LENGTH) { + hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, + "MD2 sigature have wrong length"); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + + MD2_Init(&m); + MD2_Update(&m, data->data, data->length); + MD2_Final (digest, &m); + + if (memcmp(digest, sig->data, MD2_DIGEST_LENGTH) != 0) { + hx509_set_error_string(context, 0, HX509_CRYPTO_BAD_SIGNATURE, + "Bad MD2 sigature"); + return HX509_CRYPTO_BAD_SIGNATURE; + } + + return 0; +} + +static const struct signature_alg heim_rsa_pkcs1_x509 = { + "rsa-pkcs1-x509", + oid_id_heim_rsa_pkcs1_x509, + hx509_signature_rsa_pkcs1_x509, + oid_id_pkcs1_rsaEncryption, + NULL, + PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG, + rsa_verify_signature, + rsa_create_signature +}; + +static const struct signature_alg pkcs1_rsa_sha1_alg = { + "rsa", + oid_id_pkcs1_rsaEncryption, + hx509_signature_rsa_with_sha1, + oid_id_pkcs1_rsaEncryption, + NULL, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG, + rsa_verify_signature, + rsa_create_signature +}; + +static const struct signature_alg rsa_with_sha256_alg = { + "rsa-with-sha256", + oid_id_pkcs1_sha256WithRSAEncryption, + hx509_signature_rsa_with_sha256, + oid_id_pkcs1_rsaEncryption, + oid_id_sha256, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG, + rsa_verify_signature, + rsa_create_signature +}; + +static const struct signature_alg rsa_with_sha1_alg = { + "rsa-with-sha1", + oid_id_pkcs1_sha1WithRSAEncryption, + hx509_signature_rsa_with_sha1, + oid_id_pkcs1_rsaEncryption, + oid_id_secsig_sha_1, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG, + rsa_verify_signature, + rsa_create_signature +}; + +static const struct signature_alg rsa_with_md5_alg = { + "rsa-with-md5", + oid_id_pkcs1_md5WithRSAEncryption, + hx509_signature_rsa_with_md5, + oid_id_pkcs1_rsaEncryption, + oid_id_rsa_digest_md5, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG, + rsa_verify_signature, + rsa_create_signature +}; + +static const struct signature_alg rsa_with_md2_alg = { + "rsa-with-md2", + oid_id_pkcs1_md2WithRSAEncryption, + hx509_signature_rsa_with_md2, + oid_id_pkcs1_rsaEncryption, + oid_id_rsa_digest_md2, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG, + rsa_verify_signature, + rsa_create_signature +}; + +static const struct signature_alg dsa_sha1_alg = { + "dsa-with-sha1", + oid_id_dsa_with_sha1, + NULL, + oid_id_dsa, + oid_id_secsig_sha_1, + PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG, + dsa_verify_signature, + /* create_signature */ NULL, +}; + +static const struct signature_alg sha256_alg = { + "sha-256", + oid_id_sha256, + hx509_signature_sha256, + NULL, + NULL, + SIG_DIGEST, + sha256_verify_signature, + sha256_create_signature +}; + +static const struct signature_alg sha1_alg = { + "sha1", + oid_id_secsig_sha_1, + hx509_signature_sha1, + NULL, + NULL, + SIG_DIGEST, + sha1_verify_signature, + sha1_create_signature +}; + +static const struct signature_alg md5_alg = { + "rsa-md5", + oid_id_rsa_digest_md5, + hx509_signature_md5, + NULL, + NULL, + SIG_DIGEST, + md5_verify_signature +}; + +static const struct signature_alg md2_alg = { + "rsa-md2", + oid_id_rsa_digest_md2, + hx509_signature_md2, + NULL, + NULL, + SIG_DIGEST, + md2_verify_signature +}; + +/* + * Order matter in this structure, "best" first for each "key + * compatible" type (type is RSA, DSA, none, etc) + */ + +static const struct signature_alg *sig_algs[] = { + &rsa_with_sha256_alg, + &rsa_with_sha1_alg, + &pkcs1_rsa_sha1_alg, + &rsa_with_md5_alg, + &rsa_with_md2_alg, + &heim_rsa_pkcs1_x509, + &dsa_sha1_alg, + &sha256_alg, + &sha1_alg, + &md5_alg, + &md2_alg, + NULL +}; + +static const struct signature_alg * +find_sig_alg(const heim_oid *oid) +{ + 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 struct hx509_private_key_ops *private_algs[] = { + &rsa_private_key_ops, + NULL +}; + +static hx509_private_key_ops * +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; +} + + +int +_hx509_verify_signature(hx509_context context, + const Certificate *signer, + const AlgorithmIdentifier *alg, + const heim_octet_string *data, + const heim_octet_string *sig) +{ + const struct signature_alg *md; + + md = 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); +} + +int +_hx509_verify_signature_bitstring(hx509_context context, + const Certificate *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); +} + +int +_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; + + if (signer && signer->ops && signer->ops->handle_alg && + (*signer->ops->handle_alg)(signer, alg, COT_SIGN)) + { + return (*signer->ops->sign)(context, signer, alg, data, + signatureAlgorithm, sig); + } + + md = 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); +} + +int +_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; +} + +int +_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; + RSAPublicKey pk; + size_t size; + + ciphertext->data = NULL; + ciphertext->length = 0; + + spi = &cert->tbsCertificate.subjectPublicKeyInfo; + + rsa = RSA_new(); + if (rsa == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + + ret = decode_RSAPublicKey(spi->subjectPublicKey.data, + spi->subjectPublicKey.length / 8, + &pk, &size); + if (ret) { + RSA_free(rsa); + hx509_set_error_string(context, 0, ret, "RSAPublicKey decode failure"); + return ret; + } + rsa->n = heim_int2BN(&pk.modulus); + rsa->e = heim_int2BN(&pk.publicExponent); + + free_RSAPublicKey(&pk); + + if (rsa->n == NULL || rsa->e == NULL) { + RSA_free(rsa); + 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(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; +} + +int +_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 < ret) + _hx509_abort("internal rsa decryption failure: ret > tosize"); + + cleartext->length = ret; + + return 0; +} + + +int +_hx509_parse_private_key(hx509_context context, + const heim_oid *key_oid, + const void *data, + size_t len, + hx509_private_key *private_key) +{ + struct hx509_private_key_ops *ops; + int ret; + + *private_key = NULL; + + ops = find_private_alg(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->import)(context, data, len, *private_key); + if (ret) + _hx509_private_key_free(private_key); + + return ret; +} + +/* + * + */ + +int +_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); +} + +int +_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, 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; +} + +int +_hx509_generate_private_key_is_ca(hx509_context context, + struct hx509_generate_private_context *ctx) +{ + ctx->isCA = 1; + return 0; +} + +int +_hx509_generate_private_key_bits(hx509_context context, + struct hx509_generate_private_context *ctx, + unsigned long bits) +{ + ctx->num_bits = bits; + return 0; +} + + +void +_hx509_generate_private_key_free(struct hx509_generate_private_context **ctx) +{ + free(*ctx); + *ctx = NULL; +} + +int +_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 = 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; +} + + +/* + * + */ + +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 md2_oid_tree[] = { 1, 2, 840, 113549, 2, 2 }; +const AlgorithmIdentifier _hx509_signature_md2_data = { + { 6, rk_UNCONST(md2_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) }, NULL +}; + +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) }, NULL +}; + +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) }, NULL +}; + +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) }, NULL +}; + +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) }, NULL +}; + +static const unsigned rsa_with_md2_oid[] ={ 1, 2, 840, 113549, 1, 1, 2 }; +const AlgorithmIdentifier _hx509_signature_rsa_with_md2_data = { + { 7, rk_UNCONST(rsa_with_md2_oid) }, NULL +}; + +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 +}; + +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_md2(void) +{ return &_hx509_signature_md2_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_with_md2(void) +{ return &_hx509_signature_rsa_with_md2_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_sha1_data; +const AlgorithmIdentifier * _hx509_crypto_default_digest_alg = + &_hx509_signature_sha1_data; +const AlgorithmIdentifier * _hx509_crypto_default_secret_alg = + &_hx509_crypto_aes128_cbc_data; + +/* + * + */ + +int +_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_private_key +_hx509_private_key_ref(hx509_private_key key) +{ + if (key->ref <= 0) + _hx509_abort("refcount <= 0"); + key->ref++; + if (key->ref == 0) + _hx509_abort("refcount == 0"); + return key; +} + +const char * +_hx509_private_pem_name(hx509_private_key key) +{ + return key->ops->pemtype; +} + +int +_hx509_private_key_free(hx509_private_key *key) +{ + if (key == NULL || *key == NULL) + return 0; + + if ((*key)->ref <= 0) + _hx509_abort("refcount <= 0"); + if (--(*key)->ref > 0) + return 0; + + if ((*key)->private_key.rsa) + RSA_free((*key)->private_key.rsa); + (*key)->private_key.rsa = NULL; + free(*key); + *key = NULL; + return 0; +} + +void +_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 = oid_id_pkcs1_sha1WithRSAEncryption(); + key->md = &pkcs1_rsa_sha1_alg; +} + +int +_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; +} + +int +_hx509_private_key_exportable(hx509_private_key key) +{ + if (key->ops->export == NULL) + return 0; + return 1; +} + +BIGNUM * +_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); +} + +int +_hx509_private_key_export(hx509_context context, + const hx509_private_key key, + heim_octet_string *data) +{ + if (key->ops->export == NULL) { + hx509_clear_error_string(context); + return HX509_UNIMPLEMENTED_OPERATION; + } + return (*key->ops->export)(context, key, data); +} + +/* + * + */ + +struct hx509cipher { + const char *name; + const heim_oid *(*oid_func)(void); + 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; + const struct hx509cipher *cipher; + const EVP_CIPHER *c; + heim_octet_string key; + heim_oid oid; + void *param; +}; + +/* + * + */ + +static const heim_oid * +oid_private_rc2_40(void) +{ + static unsigned oid_data[] = { 127, 1 }; + static const heim_oid oid = { 2, oid_data }; + + return &oid; +} + + +/* + * + */ + +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", + oid_id_pkcs3_rc2_cbc, + NULL, + EVP_rc2_cbc, + CMSRC2CBCParam_get, + CMSRC2CBCParam_set + }, + { + "rc2-cbc", + oid_id_rsadsi_rc2_cbc, + NULL, + EVP_rc2_cbc, + CMSRC2CBCParam_get, + CMSRC2CBCParam_set + }, + { + "rc2-40-cbc", + oid_private_rc2_40, + NULL, + EVP_rc2_40_cbc, + CMSRC2CBCParam_get, + CMSRC2CBCParam_set + }, + { + "des-ede3-cbc", + oid_id_pkcs3_des_ede3_cbc, + NULL, + EVP_des_ede3_cbc, + CMSCBCParam_get, + CMSCBCParam_set + }, + { + "des-ede3-cbc", + oid_id_rsadsi_des_ede3_cbc, + hx509_crypto_des_rsdi_ede3_cbc, + EVP_des_ede3_cbc, + CMSCBCParam_get, + CMSCBCParam_set + }, + { + "aes-128-cbc", + oid_id_aes_128_cbc, + hx509_crypto_aes128_cbc, + EVP_aes_128_cbc, + CMSCBCParam_get, + CMSCBCParam_set + }, + { + "aes-192-cbc", + oid_id_aes_192_cbc, + NULL, + EVP_aes_192_cbc, + CMSCBCParam_get, + CMSCBCParam_set + }, + { + "aes-256-cbc", + 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) +{ + int i; + + for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++) + if (der_heim_oid_cmp(oid, (*ciphers[i].oid_func)()) == 0) + return &ciphers[i]; + + return NULL; +} + +static const struct hx509cipher * +find_cipher_by_name(const char *name) +{ + int i; + + for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++) + if (strcasecmp(name, ciphers[i].name) == 0) + return &ciphers[i]; + + return NULL; +} + + +const heim_oid * +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_func)(); +} + +int +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)->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; +} + +const char * +hx509_crypto_provider(hx509_crypto crypto) +{ + return "unknown"; +} + +void +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); +} + +int +hx509_crypto_set_key_name(hx509_crypto crypto, const char *name) +{ + return 0; +} + +int +hx509_crypto_set_key_data(hx509_crypto crypto, const void *data, size_t length) +{ + if (EVP_CIPHER_key_length(crypto->c) > 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; +} + +int +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; +} + +int +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); +} + +int +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); +} + +int +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; +} + +int +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; + int ret; + + *ciphertext = NULL; + + assert(EVP_CIPHER_iv_length(crypto->c) == 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; + } + + if (EVP_CIPHER_block_size(crypto->c) == 1) { + padsize = 0; + } else { + int bsize = EVP_CIPHER_block_size(crypto->c); + 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) { + int 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; +} + +int +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 (ivec && EVP_CIPHER_iv_length(crypto->c) < 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 (EVP_CIPHER_block_size(crypto->c) > 1) { + int padsize; + unsigned char *p; + int j, bsize = EVP_CIPHER_block_size(crypto->c); + + if (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; + + 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, oid_id_pbewithSHAAnd40BitRC2_CBC()) == 0) { + *c = EVP_rc2_40_cbc(); + *md = EVP_sha1(); + *s2k = PBE_string2key; + return oid_private_rc2_40(); + } else if (der_heim_oid_cmp(oid, oid_id_pbeWithSHAAnd128BitRC2_CBC()) == 0) { + *c = EVP_rc2_cbc(); + *md = EVP_sha1(); + *s2k = PBE_string2key; + return oid_id_pkcs3_rc2_cbc(); +#if 0 + } else if (der_heim_oid_cmp(oid, oid_id_pbeWithSHAAnd40BitRC4()) == 0) { + *c = EVP_rc4_40(); + *md = EVP_sha1(); + *s2k = PBE_string2key; + return NULL; + } else if (der_heim_oid_cmp(oid, oid_id_pbeWithSHAAnd128BitRC4()) == 0) { + *c = EVP_rc4(); + *md = EVP_sha1(); + *s2k = PBE_string2key; + return oid_id_pkcs3_rc4(); +#endif + } else if (der_heim_oid_cmp(oid, oid_id_pbeWithSHAAnd3_KeyTripleDES_CBC()) == 0) { + *c = EVP_des_ede3_cbc(); + *md = EVP_sha1(); + *s2k = PBE_string2key; + return oid_id_pkcs3_des_ede3_cbc(); + } + + return NULL; +} + +/* + * + */ + +int +_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; +} + +/* + * + */ + +int +_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 i, ret = 0; + + 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; +} + +/* + * + */ + + +int +_hx509_match_keys(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 const heim_oid * +find_keytype(const hx509_private_key key) +{ + const struct signature_alg *md; + + if (key == NULL) + return NULL; + + md = find_sig_alg(key->signature_alg); + if (md == NULL) + return NULL; + return (*md->key_oid)(); +} + + +int +hx509_crypto_select(const hx509_context context, + int type, + const hx509_private_key source, + hx509_peer_info peer, + AlgorithmIdentifier *selected) +{ + const AlgorithmIdentifier *def; + size_t i, j; + int ret, bits; + + memset(selected, 0, sizeof(*selected)); + + if (type == HX509_SELECT_DIGEST) { + bits = SIG_DIGEST; + def = _hx509_crypto_default_digest_alg; + } else if (type == HX509_SELECT_PUBLIC_SIG) { + bits = SIG_PUBLIC_SIG; + /* XXX depend on `source´ and `peer´ */ + 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; +} + +int +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].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; +} + +void +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/crypto/heimdal/lib/hx509/data/bleichenbacher-bad.pem b/crypto/heimdal/lib/hx509/data/bleichenbacher-bad.pem new file mode 100644 index 0000000..2c71932 --- /dev/null +++ b/crypto/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/crypto/heimdal/lib/hx509/data/bleichenbacher-good.pem b/crypto/heimdal/lib/hx509/data/bleichenbacher-good.pem new file mode 100644 index 0000000..409147bd --- /dev/null +++ b/crypto/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/crypto/heimdal/lib/hx509/data/bleichenbacher-sf-pad-correct.pem b/crypto/heimdal/lib/hx509/data/bleichenbacher-sf-pad-correct.pem new file mode 100644 index 0000000..3e73f5d --- /dev/null +++ b/crypto/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/crypto/heimdal/lib/hx509/data/ca.crt b/crypto/heimdal/lib/hx509/data/ca.crt new file mode 100644 index 0000000..76fa2c4 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/ca.crt @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICbDCCAdWgAwIBAgIJALeUXoWyGYBYMA0GCSqGSIb3DQEBBQUAMCoxGzAZBgNV +BAMMEmh4NTA5IFRlc3QgUm9vdCBDQTELMAkGA1UEBhMCU0UwHhcNMDcxMTE1MDY1 +ODU2WhcNMTcxMTEyMDY1ODU2WjAqMRswGQYDVQQDDBJoeDUwOSBUZXN0IFJvb3Qg +Q0ExCzAJBgNVBAYTAlNFMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHcvJb +yJXPhM9HHq1hU6d2Cu1fW9o1CvObirn1SNZg+pTnQgO9Lv4VjQQfltNK0aovyLJa +UdbAbsRCfH+79YY2tU76x8aXpUri0DfUv5PGscIZzW7WULaaXxBgHo1owzmhc1Qj +F9JDEurJXGFEZaDsPcEwY40RjrKDL8SXzEoEwwIDAQABo4GZMIGWMB0GA1UdDgQW +BBSM5w21xd5phXUsCKHeUxUwnKHoADBaBgNVHSMEUzBRgBSM5w21xd5phXUsCKHe +UxUwnKHoAKEupCwwKjEbMBkGA1UEAwwSaHg1MDkgVGVzdCBSb290IENBMQswCQYD +VQQGEwJTRYIJALeUXoWyGYBYMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgHmMA0G +CSqGSIb3DQEBBQUAA4GBAIBa6mq1aytlbhixD6q4PROg7P1OGX6nr5CkC96CC+Xp +5UTLZEVIddkrBswNAAS0p5eEorO8xD9eT5ztZ0oYITymsO1sEIfDLks+LhdBoyF7 +TX24INRwjlqsC8UlbRFoClxIMNhrMwcC3oZ4oLddV2OmA0IOG6yHXvEOQq0sTotr +-----END CERTIFICATE----- diff --git a/crypto/heimdal/lib/hx509/data/ca.key b/crypto/heimdal/lib/hx509/data/ca.key new file mode 100644 index 0000000..924c52d --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/ca.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDHcvJbyJXPhM9HHq1hU6d2Cu1fW9o1CvObirn1SNZg+pTnQgO9 +Lv4VjQQfltNK0aovyLJaUdbAbsRCfH+79YY2tU76x8aXpUri0DfUv5PGscIZzW7W +ULaaXxBgHo1owzmhc1QjF9JDEurJXGFEZaDsPcEwY40RjrKDL8SXzEoEwwIDAQAB +AoGAcRFgBdpr224eF+JzRganm8rMENBAnutreRUnIL+/ENFd0tBg0EIwtsTvvnzB +odvEkDxFp+BXT1Y8Grj7rPGeuKq7537J43Go02fSC7z4i3HDhSmv1SXE59hiES4F +ktyR2D7N+A/RPCckS4JM/zG4ZkucqKg/NnVpbdTpl0P2oSkCQQDoDkPde5vfWeXG +wmAgm5HPbyEmDBXQMlYDgNd448TmObRpjr0dyyr5zDgFJkOpOmv6WUMUxGILam3k +hCDqQqHPAkEA3AdgsMafqkR+OJmZT/gIDYb+mU8DFH6+WcUPxk+qbAa8JWg4VD30 +tpOKwZu4an1kExHnsVTqKOoW1cYmtYDuzQJAJ+78gsrYwhDoV9HvVO0wpG/NVozR +3CgtYSD085rOsYfQojGsHcputNoN8eTp09934Xcm8hXxgWFpU9/hAi9BRQJACKG1 +dlnka56SQRAthoiZcEZqeIM0ALrUJttnOgVoDyLYgLMs+okPr5XsLJo6StsucN0T +9M36/a3pRWunmxk6xQJBAOaD3sdIMLtGpFFOIQgkNUD9rOqXpi87h3ecmJCuG82w +B6kRNvpZz33U2FowFQtGBdvUBsbzlRzYDMrWniC6YKc= +-----END RSA PRIVATE KEY----- diff --git a/crypto/heimdal/lib/hx509/data/crl1.crl b/crypto/heimdal/lib/hx509/data/crl1.crl new file mode 100644 index 0000000..14aecf4 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/crl1.crl @@ -0,0 +1,8 @@ +-----BEGIN X509 CRL----- +MIIBBDBvMA0GCSqGSIb3DQEBBQUAMCoxGzAZBgNVBAMMEmh4NTA5IFRlc3QgUm9v +dCBDQTELMAkGA1UEBhMCU0UXDTA3MTExNTA2NTkwMFoXDTE3MDkyMzA2NTkwMFow +FDASAgEDFw0wNzExMTUwNjU5MDBaMA0GCSqGSIb3DQEBBQUAA4GBAGYUroSt3oVI +0mjphSYqtpzDavF6xVM7bQrQEW+ZhzG7VynJdJaPgaJRaEHj9CNlJT1GF5WOY180 +wWuZEqXUV144snZ7YkSdsNOQRSmnHp8Fl6Sjdya3G55FoJHmhZ2JvscyZpb/Vh8N +NoMICB27iYqCzVlK9NkT5neCmomv/mDn +-----END X509 CRL----- diff --git a/crypto/heimdal/lib/hx509/data/crl1.der b/crypto/heimdal/lib/hx509/data/crl1.der Binary files differnew file mode 100644 index 0000000..6d29196 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/crl1.der diff --git a/crypto/heimdal/lib/hx509/data/gen-req.sh b/crypto/heimdal/lib/hx509/data/gen-req.sh new file mode 100644 index 0000000..4926399 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/gen-req.sh @@ -0,0 +1,316 @@ +#!/bin/sh +# $Id: gen-req.sh 21786 2007-08-01 19:37:45Z lha $ +# +# This script need openssl 0.9.8a or newer, so it can parse the +# otherName section for pkinit certificates. +# + +openssl=$HOME/src/openssl/openssl-0.9.8e/apps/openssl + +gen_cert() +{ + ${openssl} req \ + -new \ + -subj "$1" \ + -config openssl.cnf \ + -newkey rsa:1024 \ + -sha1 \ + -nodes \ + -keyout out.key \ + -out cert.req > /dev/null 2>/dev/null + + if [ "$3" = "ca" ] ; then + ${openssl} x509 \ + -req \ + -days 3650 \ + -in cert.req \ + -extfile openssl.cnf \ + -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 3650 \ + -out cert.crt \ + -CA $2.crt \ + -CAkey $2.key \ + -CAcreateserial \ + -extfile openssl.cnf \ + -extensions $4 + + name=$5 + else + + ${openssl} ca \ + -name $4 \ + -days 3650 \ + -cert $2.crt \ + -keyfile $2.key \ + -in cert.req \ + -out cert.crt \ + -outdir . \ + -batch \ + -config openssl.cnf + + 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" +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 openssl.cnf + +${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 \ + -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 openssl.cnf + +${openssl} crl -in crl1.crl -outform der -out crl1.der diff --git a/crypto/heimdal/lib/hx509/data/j.pem b/crypto/heimdal/lib/hx509/data/j.pem new file mode 100644 index 0000000..45ae8e8 --- /dev/null +++ b/crypto/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/crypto/heimdal/lib/hx509/data/kdc.crt b/crypto/heimdal/lib/hx509/data/kdc.crt new file mode 100644 index 0000000..7dc3835 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/kdc.crt @@ -0,0 +1,59 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7 (0x7) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Nov 15 06:58:58 2007 GMT + Not After : Nov 12 06:58:58 2017 GMT + Subject: C=SE, CN=kdc + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bb:fa:14:24:35:9f:cb:82:91:20:b9:44:ec:4d: + f8:e4:1b:68:3f:6a:4d:d1:56:3e:28:25:6e:ab:aa: + 8b:6b:9c:59:ce:67:cc:27:61:4f:ff:18:a5:56:81: + a1:94:c4:33:f9:20:54:e5:1f:5a:47:43:ee:8f:52: + 8a:9f:97:6b:73:92:a3:e1:fd:9e:0b:04:36:2b:b2: + 72:bd:80:ff:ae:5a:e1:9b:bb:d8:77:c8:fe:f8:3b: + 3f:b9:51:56:6e:97:c2:2a:76:ea:56:d8:46:67:45: + 33:6f:b1:74:cf:2b:dd:11:32:1f:d7:a9:e9:2a:e2: + 0f:a8:dd:b1:94:85:87:dd:b5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Extended Key Usage: + pkkdcekuoid + X509v3 Subject Key Identifier: + 51:75:26:1A:E0:16:0F:69:A8:B4:98:80:EB:C8:49:A6:D0:C6:24:C1 + X509v3 Subject Alternative Name: + othername:<unsupported> + Signature Algorithm: sha1WithRSAEncryption + 7a:f7:7c:cf:2d:87:aa:93:49:b1:05:2a:ea:ee:75:97:22:02: + 5a:a1:2c:e3:e1:9d:be:48:0c:75:26:e0:84:f0:2a:90:5a:15: + dd:7c:58:65:ab:79:05:85:40:54:35:e1:57:58:96:aa:32:68: + f2:bd:cc:b5:9a:1c:f5:d7:49:01:44:ce:fc:22:55:3c:86:d6: + c2:ed:46:e6:dc:a7:c5:48:3f:ac:0c:10:ba:b9:e2:e8:78:37: + 79:f7:d5:da:c0:8e:74:09:64:ff:bb:36:24:d4:c7:4d:c3:93: + c2:d7:3a:32:97:b9:e1:79:ea:82:3a:42:69:ec:e4:ec:48:d5: + 3f:90 +-----BEGIN CERTIFICATE----- +MIICVDCCAb2gAwIBAgIBBzANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMB4XDTA3MTExNTA2NTg1OFoXDTE3 +MTExMjA2NTg1OFowGzELMAkGA1UEBhMCU0UxDDAKBgNVBAMMA2tkYzCBnzANBgkq +hkiG9w0BAQEFAAOBjQAwgYkCgYEAu/oUJDWfy4KRILlE7E345BtoP2pN0VY+KCVu +q6qLa5xZzmfMJ2FP/xilVoGhlMQz+SBU5R9aR0Puj1KKn5drc5Kj4f2eCwQ2K7Jy +vYD/rlrhm7vYd8j++Ds/uVFWbpfCKnbqVthGZ0Uzb7F0zyvdETIf16npKuIPqN2x +lIWH3bUCAwEAAaOBmDCBlTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DASBgNVHSUE +CzAJBgcrBgEFAgMFMB0GA1UdDgQWBBRRdSYa4BYPaai0mIDryEmm0MYkwTBIBgNV +HREEQTA/oD0GBisGAQUCAqAzMDGgDRsLVEVTVC5INUwuU0WhIDAeoAMCAQGhFzAV +GwZrcmJ0Z3QbC1RFU1QuSDVMLlNFMA0GCSqGSIb3DQEBBQUAA4GBAHr3fM8th6qT +SbEFKurudZciAlqhLOPhnb5IDHUm4ITwKpBaFd18WGWreQWFQFQ14VdYlqoyaPK9 +zLWaHPXXSQFEzvwiVTyG1sLtRubcp8VIP6wMELq54uh4N3n31drAjnQJZP+7NiTU +x03Dk8LXOjKXueF56oI6Qmns5OxI1T+Q +-----END CERTIFICATE----- diff --git a/crypto/heimdal/lib/hx509/data/kdc.key b/crypto/heimdal/lib/hx509/data/kdc.key new file mode 100644 index 0000000..01fca65 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/kdc.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQC7+hQkNZ/LgpEguUTsTfjkG2g/ak3RVj4oJW6rqotrnFnOZ8wn +YU//GKVWgaGUxDP5IFTlH1pHQ+6PUoqfl2tzkqPh/Z4LBDYrsnK9gP+uWuGbu9h3 +yP74Oz+5UVZul8IqdupW2EZnRTNvsXTPK90RMh/Xqekq4g+o3bGUhYfdtQIDAQAB +AoGBAJXwJO65A0v+SqqyfSKME1JH9kBXF9k5lHzLVtqBP5JHdW7pZnOm8HtG+mLl +JbCXS+mUe4MDHiyoJ/qUWVRxIFgBBEQpaYxdyW8d+SpCnR53hBa3t0yxr3yZ0XCc +u4lkKaCCQM5aPZqlbEkyR0Hm+lXPKbW+Sgm18fm2zPJ/2EXhAkEA8RO+dydMR7LV +8PdOvMkENwwnkUQTI3YjoRy0yV9UV+x3JDdBufOOjObrXIg/jDkg3PyOE5JBo/EZ +u1OyFFbyPQJBAMec4B3+ZyOPeH1OodSWfL/0AFCSZyOs1UgEC7vorMJ8i0eHDIsT +Uie1xNlrfrjnXTvMG7woFZOvNXBJkxCXKNkCQQCyMX/lnxyZGq1csdB3ZrZA4jEV +BRaIbbikTA2tk1NKsjTWhimFA2xo5f8upF8kjM2nyt5RxRfT0FDO0Gye8C2ZAkBq +CJYwuJwXErZBcgya/dmEqduk8TAijkO5fpSxG7bxlPDzbPSnx/qjJ3ZKvERTemtX +QWQWPgDAM5kibaLWdEV5AkAJn7iP495Cbac0y3zihgK/M70M9y1WB0TbumpTVpg2 +taw3NwTjQlGnFj64dJIj+hgCOGYJ7H1Gt7JOi10NRtbd +-----END RSA PRIVATE KEY----- diff --git a/crypto/heimdal/lib/hx509/data/key.der b/crypto/heimdal/lib/hx509/data/key.der Binary files differnew file mode 100644 index 0000000..e7c665e --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/key.der diff --git a/crypto/heimdal/lib/hx509/data/key2.der b/crypto/heimdal/lib/hx509/data/key2.der Binary files differnew file mode 100644 index 0000000..fe3f413 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/key2.der diff --git a/crypto/heimdal/lib/hx509/data/nist-data b/crypto/heimdal/lib/hx509/data/nist-data new file mode 100644 index 0000000..80333bb --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/nist-data @@ -0,0 +1,91 @@ +# $Id: nist-data 21917 2007-08-16 13:54:25Z lha $ +# 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/crypto/heimdal/lib/hx509/data/nist-data2 b/crypto/heimdal/lib/hx509/data/nist-data2 new file mode 100644 index 0000000..491beac --- /dev/null +++ b/crypto/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/crypto/heimdal/lib/hx509/data/no-proxy-test.crt b/crypto/heimdal/lib/hx509/data/no-proxy-test.crt new file mode 100644 index 0000000..d57802e --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/no-proxy-test.crt @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICDDCCAXWgAwIBAgIJAI8UaHGQmUvOMA0GCSqGSIb3DQEBBQUAMCExCzAJBgNV +BAYTAlNFMRIwEAYDVQQDDAlUZXN0IGNlcnQwHhcNMDcxMTE1MDY1ODU5WhcNMTcx +MTEyMDY1ODU5WjA0MQswCQYDVQQGEwJTRTESMBAGA1UEAwwJVGVzdCBjZXJ0MREw +DwYDVQQDDAhuby1wcm94eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvF58 +Sgq1QTZwsXyFvMTo2Iit/NLZupuIlJgctZJ51EOaFBmTfqt/PgxQKmgqQhgFW+HT +8WPdvvfUxjwe4BiIORYoCX8pl/wGFCa70zUC7/5IoMmhb9XBrecOxswRNK8EvGhF +67z2uDUS4LASuy7ng8HSuAM0PCHYnGmqeYrR6jUCAwEAAaM5MDcwCQYDVR0TBAIw +ADALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFJ+WD/mqMrbcBts4x0tXv0CflIcZMA0G +CSqGSIb3DQEBBQUAA4GBAEAODiL2ZL2ZhkklFbHXSg/ZEkUs1Oewpg+bDO6xjute +hnarKTrWFWiSgQ9yhZMa8klaNCdHjDo0Q5borQeVzp027cemLdnLyxusSuIJRqy+ +mZtNl7533q+oKWydZtvNmXRlGi5HmJV5JAjEXbadqUnlRJ/CdN1WvdwLWfvbW5DL +-----END CERTIFICATE----- diff --git a/crypto/heimdal/lib/hx509/data/no-proxy-test.key b/crypto/heimdal/lib/hx509/data/no-proxy-test.key new file mode 100644 index 0000000..1c47937 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/no-proxy-test.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQC8XnxKCrVBNnCxfIW8xOjYiK380tm6m4iUmBy1knnUQ5oUGZN+ +q38+DFAqaCpCGAVb4dPxY92+99TGPB7gGIg5FigJfymX/AYUJrvTNQLv/kigyaFv +1cGt5w7GzBE0rwS8aEXrvPa4NRLgsBK7LueDwdK4AzQ8Idicaap5itHqNQIDAQAB +AoGBAJt0CnR8U8tGp0gCMMhxZIvWeGfOhnr3AodG5WJ/SGWBiLWPyeZel7rYJIxq +vH0hH8MNIoDy3rxMAN+8G+rqs/elE8zeYv8FCP4jahz+HPKeJIjFm1MBOHZQspq7 +Y4OfoBH+EgqJjBRxuBIeCUqVhyluSsYHQFihurp3a76dHvxBAkEA7c4KjJ6mka9C +9X+Tp2EKW+h8npEEXbLIvHet9p0pzD5PhE2aVvSEAXEqxdbuFAb4LVApUdd4Quec +PXa0EOF7UQJBAMrIIV317rGPlmEXqt681KkHo30C2e6SpM6by42r+csTs+6KDZdf +uDWZKb4o9bLTj+A0LC73ySESv4PlGC+8v6UCQEIRnJy091JCfzf12fAG5fni/byQ +TcY6hcrW9V4vDA3SwgTgCqFeDc7Ywil1LXAi/5CXVOOIGcF818u7zwthmgECQCm+ +Rvgjr05IA6nbCGavsotVMjeCxcAR2fFaKu3wEAzY8npRWvjlUHNgIzKtFd8JJB4A +P3Qvt+yiAmCxYWg6T60CQHvGW0M/usmQXEGWMx+KCkm71UKcKCxDEKzZ8mI3jQ3H +b6Whs1NdsQJwIEXHB2Sb2GmTIlFjXczw7fp/ub3Dx84= +-----END RSA PRIVATE KEY----- diff --git a/crypto/heimdal/lib/hx509/data/ocsp-req1.der b/crypto/heimdal/lib/hx509/data/ocsp-req1.der Binary files differnew file mode 100644 index 0000000..869a7dc --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/ocsp-req1.der diff --git a/crypto/heimdal/lib/hx509/data/ocsp-req2.der b/crypto/heimdal/lib/hx509/data/ocsp-req2.der Binary files differnew file mode 100644 index 0000000..c1481e1 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/ocsp-req2.der diff --git a/crypto/heimdal/lib/hx509/data/ocsp-resp1-2.der b/crypto/heimdal/lib/hx509/data/ocsp-resp1-2.der Binary files differnew file mode 100644 index 0000000..98d88e4 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/ocsp-resp1-2.der diff --git a/crypto/heimdal/lib/hx509/data/ocsp-resp1-3.der b/crypto/heimdal/lib/hx509/data/ocsp-resp1-3.der Binary files differnew file mode 100644 index 0000000..4c65016 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/ocsp-resp1-3.der diff --git a/crypto/heimdal/lib/hx509/data/ocsp-resp1-ca.der b/crypto/heimdal/lib/hx509/data/ocsp-resp1-ca.der Binary files differnew file mode 100644 index 0000000..2450168 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/ocsp-resp1-ca.der diff --git a/crypto/heimdal/lib/hx509/data/ocsp-resp1-keyhash.der b/crypto/heimdal/lib/hx509/data/ocsp-resp1-keyhash.der Binary files differnew file mode 100644 index 0000000..19cf6c8 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/ocsp-resp1-keyhash.der diff --git a/crypto/heimdal/lib/hx509/data/ocsp-resp1-ocsp-no-cert.der b/crypto/heimdal/lib/hx509/data/ocsp-resp1-ocsp-no-cert.der Binary files differnew file mode 100644 index 0000000..460b5f7 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/ocsp-resp1-ocsp-no-cert.der diff --git a/crypto/heimdal/lib/hx509/data/ocsp-resp1-ocsp.der b/crypto/heimdal/lib/hx509/data/ocsp-resp1-ocsp.der Binary files differnew file mode 100644 index 0000000..87173ff --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/ocsp-resp1-ocsp.der diff --git a/crypto/heimdal/lib/hx509/data/ocsp-resp1.der b/crypto/heimdal/lib/hx509/data/ocsp-resp1.der Binary files differnew file mode 100644 index 0000000..8546eba --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/ocsp-resp1.der diff --git a/crypto/heimdal/lib/hx509/data/ocsp-resp2.der b/crypto/heimdal/lib/hx509/data/ocsp-resp2.der Binary files differnew file mode 100644 index 0000000..0ba588a --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/ocsp-resp2.der diff --git a/crypto/heimdal/lib/hx509/data/ocsp-responder.crt b/crypto/heimdal/lib/hx509/data/ocsp-responder.crt new file mode 100644 index 0000000..fb55a8a --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/ocsp-responder.crt @@ -0,0 +1,56 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Nov 15 06:58:56 2007 GMT + Not After : Nov 12 06:58:56 2017 GMT + Subject: C=SE, CN=OCSP responder + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d9:10:2f:04:de:99:10:61:02:ff:4e:b5:54:6f: + 98:80:70:fb:a1:e0:97:ee:a9:0f:74:47:a9:8c:a5: + 86:ff:b8:ea:80:d9:ae:45:07:bd:33:93:e2:f4:f1: + dd:dc:86:6e:9a:6c:b7:67:11:50:ad:9c:b0:0f:68: + 5d:4d:74:2a:24:4e:5e:c6:c0:9e:6a:a2:ed:80:31: + d9:ac:79:c7:09:07:1f:9c:c3:12:33:88:72:9d:99: + c5:f4:fd:c6:a1:9f:09:04:e0:7d:b0:ed:1f:91:4c: + 8e:de:9b:6d:7d:cb:2e:83:32:0e:32:57:f1:16:07: + ed:69:fc:0e:a8:2a:ad:82:9d + 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: + 9C:BE:33:AF:C2:52:C6:F2:46:5F:A8:67:71:02:F1:70:4B:A7:B7:14 + Signature Algorithm: sha1WithRSAEncryption + 8b:c5:8e:d6:dc:ba:e3:77:da:66:2b:be:c4:a6:4c:b0:30:6d: + fd:26:3d:8d:1d:ad:c5:8c:88:61:86:0a:da:48:e8:39:cf:c5: + 83:98:e7:f9:ff:92:a7:ba:fe:b4:b4:6c:bb:84:17:fd:e3:71: + 9e:a7:39:af:d3:08:0b:1f:05:29:cf:ef:e4:3c:82:7e:ee:aa: + 4a:19:3b:17:e6:e9:2d:b4:f7:4f:e2:f3:6b:04:20:58:42:fa: + e2:b6:d4:80:c4:db:22:32:ce:cb:59:23:8b:df:ba:87:bb:bf: + 4e:ea:b0:1e:7a:73:b4:c9:06:aa:f1:59:cf:d3:28:db:d2:6c: + a0:dd +-----BEGIN CERTIFICATE----- +MIICHzCCAYigAwIBAgIBATANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMB4XDTA3MTExNTA2NTg1NloXDTE3 +MTExMjA2NTg1NlowJjELMAkGA1UEBhMCU0UxFzAVBgNVBAMMDk9DU1AgcmVzcG9u +ZGVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZEC8E3pkQYQL/TrVUb5iA +cPuh4JfuqQ90R6mMpYb/uOqA2a5FB70zk+L08d3chm6abLdnEVCtnLAPaF1NdCok +Tl7GwJ5qou2AMdmseccJBx+cwxIziHKdmcX0/cahnwkE4H2w7R+RTI7em219yy6D +Mg4yV/EWB+1p/A6oKq2CnQIDAQABo1kwVzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF +4DAeBgNVHSUEFzAVBgkrBgEFBQcwAQUGCCsGAQUFBwMJMB0GA1UdDgQWBBScvjOv +wlLG8kZfqGdxAvFwS6e3FDANBgkqhkiG9w0BAQUFAAOBgQCLxY7W3Lrjd9pmK77E +pkywMG39Jj2NHa3FjIhhhgraSOg5z8WDmOf5/5Knuv60tGy7hBf943Gepzmv0wgL +HwUpz+/kPIJ+7qpKGTsX5ukttPdP4vNrBCBYQvrittSAxNsiMs7LWSOL37qHu79O +6rAeenO0yQaq8VnP0yjb0myg3Q== +-----END CERTIFICATE----- diff --git a/crypto/heimdal/lib/hx509/data/ocsp-responder.key b/crypto/heimdal/lib/hx509/data/ocsp-responder.key new file mode 100644 index 0000000..24369bc --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/ocsp-responder.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDZEC8E3pkQYQL/TrVUb5iAcPuh4JfuqQ90R6mMpYb/uOqA2a5F +B70zk+L08d3chm6abLdnEVCtnLAPaF1NdCokTl7GwJ5qou2AMdmseccJBx+cwxIz +iHKdmcX0/cahnwkE4H2w7R+RTI7em219yy6DMg4yV/EWB+1p/A6oKq2CnQIDAQAB +AoGBALXDXowmVmgnxFnEMAWvmTVc5unL5437VayaYbkb1ysGTqBtKAg4DdBF81QH +wS/sBmwbw4x0LGnk/m04iIDWWH4ZTH0HHthLxTiIrGHenS01V4Ucq1EjhYNJW/bk +8FGf91UDknZrEnvPFQxvdSLHVSB+WHgqkX8WXPc7MwoJ7HblAkEA9pmjB8TXxeky +B8+0G65u3QDWMzmfw12oHgKHnHxKyL/gamHERNPJ0NsFE4BtsSF1LJQYCw189s8m +GDpa0uW0iwJBAOFWUiJSYYVTSdcmfjI99XUCo9rXEkaJXY0etjK5q+rK21mrkWNQ +M7fWVZDbQZfbTP1LiUak+qjz64J9/iOogncCQEXUT6Qdi3RRiodHu5qzFFWkrQMo +aCMsXDTTRo97arnaC7RUJv3OczGfM5rIHUexT7rl3MEUerRxCDqIG7voq+0CQQDE +806sgvaLsoVqkFFilnbwg5M1lh96GVv0GTDEWzZg7FcWI/faJuJdPu/gwVKuaNX8 +2cWtQkt32mIw1vCGuCT3AkAfubHAXeiBHHE95jLtQ98s4KzOaZtFnQfn14c8nGS0 +2qUv1RHYZEVHYnsOZs3pLyOdxrZOlOSE6gKHCGVHoUKJ +-----END RSA PRIVATE KEY----- diff --git a/crypto/heimdal/lib/hx509/data/openssl.cnf b/crypto/heimdal/lib/hx509/data/openssl.cnf new file mode 100644 index 0000000..7fe3b64 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/openssl.cnf @@ -0,0 +1,182 @@ +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 +certs = . + +[ocsp] +database = index.txt +serial = serial +x509_extensions = ocsp_cert +default_md=sha1 +policy = policy_match +certs = . + +[usr_ke] +database = index.txt +serial = serial +x509_extensions = usr_cert_ke +default_md=sha1 +policy = policy_match +certs = . + +[usr_ds] +database = index.txt +serial = serial +x509_extensions = usr_cert_ds +default_md=sha1 +policy = policy_match +certs = . + +[pkinit_client] +database = index.txt +serial = serial +x509_extensions = pkinit_client_cert +default_md=sha1 +policy = policy_match +certs = . + +[pkinit_kdc] +database = index.txt +serial = serial +x509_extensions = pkinit_kdc_cert +default_md=sha1 +policy = policy_match +certs = . + +[https] +database = index.txt +serial = serial +x509_extensions = https_cert +default_md=sha1 +policy = policy_match +certs = . + +[subca] +database = index.txt +serial = serial +x509_extensions = v3_ca +default_md=sha1 +policy = policy_match +certs = . + + +[ req ] +distinguished_name = req_distinguished_name +x509_extensions = v3_ca # The extentions 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_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 + +[pkinitc_principal_seq] +name_type = EXP:0, INTEGER:1 +name_string = EXP:1, SEQUENCE:pkinitc_principals + +[pkinitc_principals] +princ1 = GeneralString:bar + +[ 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/crypto/heimdal/lib/hx509/data/pkinit-proxy-chain.crt b/crypto/heimdal/lib/hx509/data/pkinit-proxy-chain.crt new file mode 100644 index 0000000..7349a62 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/pkinit-proxy-chain.crt @@ -0,0 +1,70 @@ +-----BEGIN CERTIFICATE----- +MIICMTCCAZqgAwIBAgIJAJWfAgX+rDGvMA0GCSqGSIb3DQEBBQUAMB4xCzAJBgNV +BAYTAlNFMQ8wDQYDVQQDDAZwa2luaXQwHhcNMDcxMTE1MDY1ODU3WhcNMTcxMTEy +MDY1ODU3WjA1MQswCQYDVQQGEwJTRTEPMA0GA1UEAwwGcGtpbml0MRUwEwYDVQQD +DAxwa2luaXQtcHJveHkwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJk+5riF +ML9djk75CGm9WUN37N+EKXZvLS1/jLsQbxOWPnfZ/bHPpnI2I4EEavSQUgrlbpLf +5IZsxlAFtokSROpef1MQ3oyJFom8c1Ut37zEJL13m4pjUZjr8Ky+OUsWNVieRIXU +eHw2+Ny8a5y3XOygCJWDzaCTcm+nvfTmVsr9AgMBAAGjYDBeMAkGA1UdEwQCMAAw +CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBQRgztmDHmF1DecOPint9iafFNckDAlBggr +BgEFBQcBDgEB/wQWMBQCAQAwDwYIKwYBBQUHFQAEA2ZvbzANBgkqhkiG9w0BAQUF +AAOBgQCYm9bHTRfvEpjnKXQz9t8Uh9L+prU2+BMDClnDHsBE/Pb1vH40rOIT2sV8 +KQnjo+TVlvHXDxUy/HMY5O/5umLbzP4xr6mWwP5B2K5y566WHThz2ltcRgcmbRrn +eOzN87+Gt1XqrTIlFftvxGX9U0PxyxFTASAOiv0hFvZN5GxYzQ== +-----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: Nov 15 06:58:57 2007 GMT + Not After : Nov 12 06:58:57 2017 GMT + Subject: C=SE, CN=pkinit + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a3:44:b1:8a:42:9d:d0:3f:30:de:e8:66:42:c1: + f1:c9:98:8f:d2:bd:eb:59:67:3d:5e:0e:35:ca:3b: + b8:91:b0:fc:e5:22:3a:2d:62:81:56:bb:51:77:60: + ac:83:43:75:87:ce:f1:f6:bd:ab:f2:07:c5:8d:d5: + b8:56:9e:8e:45:93:bd:c6:ac:5d:20:3e:cb:14:e8: + 10:07:b9:5e:07:ac:56:13:48:1b:84:c7:30:62:f4: + e4:19:67:b5:1b:3a:ac:af:0b:92:e2:00:90:2f:81: + 75:b6:63:3f:43:a5:e9:76:ee:33:75:74:b2:76:5d: + a5:76:f2:f9:30:68:ec:e8:47 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 66:BB:EC:4F:F0:52:7E:D1:F4:F4:F9:CD:E9:B6:C7:C4:FC:2A:2F:4F + X509v3 Subject Alternative Name: + othername:<unsupported> + Signature Algorithm: sha1WithRSAEncryption + 1f:bd:87:72:d7:85:93:f9:96:97:6f:25:2f:89:1f:09:64:ff: + da:44:92:d0:59:6e:4f:cf:29:d7:5a:78:64:40:1c:3d:a5:80: + e9:b9:92:85:44:2e:25:ab:5c:8d:35:4b:5b:47:c6:79:61:cf: + b9:75:55:0b:20:6a:ad:ec:f5:0f:47:1e:e7:72:b0:b6:61:0f: + d6:84:e3:e4:29:05:4d:d1:7c:7b:a6:7b:6f:b2:af:9a:6b:dd: + 81:ae:5d:c1:7b:74:11:86:18:2e:38:eb:ed:33:03:f6:05:4b: + ec:d7:7d:53:6c:71:01:86:fb:fb:63:dd:5b:cb:10:85:96:f2: + 43:43 +-----BEGIN CERTIFICATE----- +MIICMTCCAZqgAwIBAgIBBjANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMB4XDTA3MTExNTA2NTg1N1oXDTE3 +MTExMjA2NTg1N1owHjELMAkGA1UEBhMCU0UxDzANBgNVBAMMBnBraW5pdDCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAo0SxikKd0D8w3uhmQsHxyZiP0r3rWWc9 +Xg41yju4kbD85SI6LWKBVrtRd2Csg0N1h87x9r2r8gfFjdW4Vp6ORZO9xqxdID7L +FOgQB7leB6xWE0gbhMcwYvTkGWe1GzqsrwuS4gCQL4F1tmM/Q6Xpdu4zdXSydl2l +dvL5MGjs6EcCAwEAAaNzMHEwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwHQYDVR0O +BBYEFGa77E/wUn7R9PT5zem2x8T8Ki9PMDgGA1UdEQQxMC+gLQYGKwYBBQICoCMw +IaANGwtURVNULkg1TC5TRaEQMA6gAwIBAaEHMAUbA2JhcjANBgkqhkiG9w0BAQUF +AAOBgQAfvYdy14WT+ZaXbyUviR8JZP/aRJLQWW5PzynXWnhkQBw9pYDpuZKFRC4l +q1yNNUtbR8Z5Yc+5dVULIGqt7PUPRx7ncrC2YQ/WhOPkKQVN0Xx7pntvsq+aa92B +rl3Be3QRhhguOOvtMwP2BUvs131TbHEBhvv7Y91byxCFlvJDQw== +-----END CERTIFICATE----- diff --git a/crypto/heimdal/lib/hx509/data/pkinit-proxy.crt b/crypto/heimdal/lib/hx509/data/pkinit-proxy.crt new file mode 100644 index 0000000..3867a89 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/pkinit-proxy.crt @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICMTCCAZqgAwIBAgIJAJWfAgX+rDGvMA0GCSqGSIb3DQEBBQUAMB4xCzAJBgNV +BAYTAlNFMQ8wDQYDVQQDDAZwa2luaXQwHhcNMDcxMTE1MDY1ODU3WhcNMTcxMTEy +MDY1ODU3WjA1MQswCQYDVQQGEwJTRTEPMA0GA1UEAwwGcGtpbml0MRUwEwYDVQQD +DAxwa2luaXQtcHJveHkwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJk+5riF +ML9djk75CGm9WUN37N+EKXZvLS1/jLsQbxOWPnfZ/bHPpnI2I4EEavSQUgrlbpLf +5IZsxlAFtokSROpef1MQ3oyJFom8c1Ut37zEJL13m4pjUZjr8Ky+OUsWNVieRIXU +eHw2+Ny8a5y3XOygCJWDzaCTcm+nvfTmVsr9AgMBAAGjYDBeMAkGA1UdEwQCMAAw +CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBQRgztmDHmF1DecOPint9iafFNckDAlBggr +BgEFBQcBDgEB/wQWMBQCAQAwDwYIKwYBBQUHFQAEA2ZvbzANBgkqhkiG9w0BAQUF +AAOBgQCYm9bHTRfvEpjnKXQz9t8Uh9L+prU2+BMDClnDHsBE/Pb1vH40rOIT2sV8 +KQnjo+TVlvHXDxUy/HMY5O/5umLbzP4xr6mWwP5B2K5y566WHThz2ltcRgcmbRrn +eOzN87+Gt1XqrTIlFftvxGX9U0PxyxFTASAOiv0hFvZN5GxYzQ== +-----END CERTIFICATE----- diff --git a/crypto/heimdal/lib/hx509/data/pkinit-proxy.key b/crypto/heimdal/lib/hx509/data/pkinit-proxy.key new file mode 100644 index 0000000..d04b009 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/pkinit-proxy.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQCZPua4hTC/XY5O+QhpvVlDd+zfhCl2by0tf4y7EG8Tlj532f2x +z6ZyNiOBBGr0kFIK5W6S3+SGbMZQBbaJEkTqXn9TEN6MiRaJvHNVLd+8xCS9d5uK +Y1GY6/CsvjlLFjVYnkSF1Hh8NvjcvGuct1zsoAiVg82gk3Jvp7305lbK/QIDAQAB +AoGAKH4TbuxariYlZT6ud2o9/PLiV0lPv2ivEleiswcrooxPo1GplGNfAszFYuDs +9gRweUqYhhy9ALwbRqfLzLpUFQUBzQ1cZlO23m48GsCPL4XJxlzE9+w/wLWWaqsK +syFax5T//iokYVa07AvFZxWpEUixewirJrhNyUafdKk8W8ECQQDKpH/pvljO6e9J +jC65aTYPzMXAUp54DMWu1+FXUyELxGp+GjAwwhESpSLEaAnZH97H6ZtTiJku3Z0n +pMsrH7WtAkEAwZi2sV8I/MjFPpti/zf6OHEJo89/SgTYIHmL6pE3tuNWhw/9Dorc +N45cMGAiGep2HQdfZFGD0OekzLGeGBj0kQJAPFdNi5HVqg945IKsqyNMKNpGDGXN +sFvFRbIc9L7ZOULMny43KV2wbcfkmW2NeS0HTqoeSXqEerMdB+AHa5jupQJADALP +gt2kjxpdsm6ti6wLaCkLMhCTkyINzqX72ke8LyqXmbWSO669zuyUJ6QvOXBkd5SX +hH/SL8nPXau/ZTtXIQJBAICcJBlgxhrUn5C12wwuQw/BZi6qK9KdVcWTapnhE7eQ +Z6k/Pbi53/aI2g1EXq7G3RrQvAhV43AW5foJWqijDdA= +-----END RSA PRIVATE KEY----- diff --git a/crypto/heimdal/lib/hx509/data/pkinit-pw.key b/crypto/heimdal/lib/hx509/data/pkinit-pw.key new file mode 100644 index 0000000..563ccf1 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/pkinit-pw.key @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,1698161265C4033B32CEB819B5D78953 + +vQnkfeICkS2/gIEv1zrJ+WaUOeRvKfUUFM6uH4/xm5Abp4DqGlkCvwb4u9dZuRUj +arlvgRc0e0CoBuQ/3gmBDlmQp+4ByiypERku8MAxsUV6LEmv2f1YfhecQSntDoJH +fNOXna8caCy4W1xhmsYgWYSVS98QkNXdLjBjLJ4/MrwzdR2SMqAzyg6eNwhWAMe1 +aUh/M9JYB04sfRUtqD67oeyBfHVhDd9kByXuRYWyNE0SW5wlmVehhnEb/YHREKHr +yOa3eRGtA4MHi7NXww4NBzOG10N9Ajq55ouMKnejFroCpevC332ijBzjTI+fo4SX +hegNDXzAIqRueGZlmBzHjkTzA8tEPM1dsbviJ5BYO3iZgWE8J1rIBx51HOZmlREC +3EWflJPhd666BnBepODMBXldkmfcfxhZxuoOrrXer+NZCsXE0z0DOLsNARR/7JvW +Ie81eQijvkur1QJO63SwT0kNm5IMJZr2Ul0QLysvjY2G/nV0bzHb8KsWqNoUPNvJ +lBUGQ2yvpeVRNR9CMm39U/CcnkLOl+z2oLUC86TdodaY6FEBmIBaakZ1rHkANWK4 +HMcN0FgdGbcRLg5PHji84g4tT+SOZa1hWEC4PC7lmRxAZP+o8Pe0tpiJzIbLPTRb +3rvnEEG3IawMIGcoUGcgIUPvHH93EMpDrflVYdXmvapzST3U8xBDzpkXZRof7APG +qAFsEB4psQEDG6KmOJ245aVWN0SBjHTLlIhUTx+m7OYl34MDoyv6Yk12i9PpKQN5 +W++QayfkJzQpV4EsR08UO615+XYCzMhCU3eozH+P39RF58rYnMLv9owjx1wL0z5R +-----END RSA PRIVATE KEY----- diff --git a/crypto/heimdal/lib/hx509/data/pkinit.crt b/crypto/heimdal/lib/hx509/data/pkinit.crt new file mode 100644 index 0000000..e8d485e --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/pkinit.crt @@ -0,0 +1,56 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 6 (0x6) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Nov 15 06:58:57 2007 GMT + Not After : Nov 12 06:58:57 2017 GMT + Subject: C=SE, CN=pkinit + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a3:44:b1:8a:42:9d:d0:3f:30:de:e8:66:42:c1: + f1:c9:98:8f:d2:bd:eb:59:67:3d:5e:0e:35:ca:3b: + b8:91:b0:fc:e5:22:3a:2d:62:81:56:bb:51:77:60: + ac:83:43:75:87:ce:f1:f6:bd:ab:f2:07:c5:8d:d5: + b8:56:9e:8e:45:93:bd:c6:ac:5d:20:3e:cb:14:e8: + 10:07:b9:5e:07:ac:56:13:48:1b:84:c7:30:62:f4: + e4:19:67:b5:1b:3a:ac:af:0b:92:e2:00:90:2f:81: + 75:b6:63:3f:43:a5:e9:76:ee:33:75:74:b2:76:5d: + a5:76:f2:f9:30:68:ec:e8:47 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 66:BB:EC:4F:F0:52:7E:D1:F4:F4:F9:CD:E9:B6:C7:C4:FC:2A:2F:4F + X509v3 Subject Alternative Name: + othername:<unsupported> + Signature Algorithm: sha1WithRSAEncryption + 1f:bd:87:72:d7:85:93:f9:96:97:6f:25:2f:89:1f:09:64:ff: + da:44:92:d0:59:6e:4f:cf:29:d7:5a:78:64:40:1c:3d:a5:80: + e9:b9:92:85:44:2e:25:ab:5c:8d:35:4b:5b:47:c6:79:61:cf: + b9:75:55:0b:20:6a:ad:ec:f5:0f:47:1e:e7:72:b0:b6:61:0f: + d6:84:e3:e4:29:05:4d:d1:7c:7b:a6:7b:6f:b2:af:9a:6b:dd: + 81:ae:5d:c1:7b:74:11:86:18:2e:38:eb:ed:33:03:f6:05:4b: + ec:d7:7d:53:6c:71:01:86:fb:fb:63:dd:5b:cb:10:85:96:f2: + 43:43 +-----BEGIN CERTIFICATE----- +MIICMTCCAZqgAwIBAgIBBjANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMB4XDTA3MTExNTA2NTg1N1oXDTE3 +MTExMjA2NTg1N1owHjELMAkGA1UEBhMCU0UxDzANBgNVBAMMBnBraW5pdDCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAo0SxikKd0D8w3uhmQsHxyZiP0r3rWWc9 +Xg41yju4kbD85SI6LWKBVrtRd2Csg0N1h87x9r2r8gfFjdW4Vp6ORZO9xqxdID7L +FOgQB7leB6xWE0gbhMcwYvTkGWe1GzqsrwuS4gCQL4F1tmM/Q6Xpdu4zdXSydl2l +dvL5MGjs6EcCAwEAAaNzMHEwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwHQYDVR0O +BBYEFGa77E/wUn7R9PT5zem2x8T8Ki9PMDgGA1UdEQQxMC+gLQYGKwYBBQICoCMw +IaANGwtURVNULkg1TC5TRaEQMA6gAwIBAaEHMAUbA2JhcjANBgkqhkiG9w0BAQUF +AAOBgQAfvYdy14WT+ZaXbyUviR8JZP/aRJLQWW5PzynXWnhkQBw9pYDpuZKFRC4l +q1yNNUtbR8Z5Yc+5dVULIGqt7PUPRx7ncrC2YQ/WhOPkKQVN0Xx7pntvsq+aa92B +rl3Be3QRhhguOOvtMwP2BUvs131TbHEBhvv7Y91byxCFlvJDQw== +-----END CERTIFICATE----- diff --git a/crypto/heimdal/lib/hx509/data/pkinit.key b/crypto/heimdal/lib/hx509/data/pkinit.key new file mode 100644 index 0000000..12b4168 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/pkinit.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQCjRLGKQp3QPzDe6GZCwfHJmI/SvetZZz1eDjXKO7iRsPzlIjot +YoFWu1F3YKyDQ3WHzvH2vavyB8WN1bhWno5Fk73GrF0gPssU6BAHuV4HrFYTSBuE +xzBi9OQZZ7UbOqyvC5LiAJAvgXW2Yz9Dpel27jN1dLJ2XaV28vkwaOzoRwIDAQAB +AoGAQTAxTwnwJvDEG4xhIDB90MdITZWk/YpaF07HLVsRA6LOJtK2td5J1A5wpaCE +4NgzeikntSPgHn/54fq+Yl9mYEAM1Uv6SimudiKe3Qk0M+bS4m/SMMlmV0eFjEh6 +ZG4NNRZmmzoaQbUiVa27fZ6362xtFGbGXJ8BjxOoTeaRn6kCQQDUwJafoKPN2dsq +ewSCjGQhVGezw12ho2eaxj7VyNWU7V4LW2LdLClbXovSnpQ7bgHEopx1e97G2du7 +1ak3BxejAkEAxHUCpbFSbBBoIdnt+VGS/8hCWl8/6YniOFOk9Qp22moaNVVZYyTT +Xpu45FeDKfm/xDwvPP9If0PDoM38tBvHDQJBAMTcmAOI/0lhRv1d62RpR9XXZkXe +huskap+6xTXIqmkt4xGbNDX3wST8rWDsv7jmJ9itpxzGy/Mwb7S1FekHNQUCQDDw +jTZFlCjDdY1pQrUnMx1w/8aPj9ZXuPkbLS616qHCaMD8gAYIuHcLB+YqPsyIINN7 +wrDJT4AUm3lFlzwu50kCQELkMFUM6rb9q/cOUQxsf023nPbObm3xJ0X4FtVhXuGi +oUAOklX1xDLSqvWySOrTXfvfF4c3qCw9DAoDtKpbCgk= +-----END RSA PRIVATE KEY----- diff --git a/crypto/heimdal/lib/hx509/data/proxy-level-test.crt b/crypto/heimdal/lib/hx509/data/proxy-level-test.crt new file mode 100644 index 0000000..0cab380 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/proxy-level-test.crt @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICUDCCAbmgAwIBAgIJAKfbLM8p28MgMA0GCSqGSIb3DQEBBQUAMDExCzAJBgNV +BAYTAlNFMRIwEAYDVQQDDAlUZXN0IGNlcnQxDjAMBgNVBAMMBXByb3h5MB4XDTA3 +MTExNTA2NTg1OVoXDTE3MTExMjA2NTg1OVowQTELMAkGA1UEBhMCU0UxEjAQBgNV +BAMMCVRlc3QgY2VydDEOMAwGA1UEAwwFcHJveHkxDjAMBgNVBAMMBWNoaWxkMIGf +MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC0hrvRoael03J8Y5gvtDMq0ZGm5ZZM +OGOhTtMnNlCpA/OKEpwMPIxiWr625wFwD7YUupvUZ7qLodf5yTN1wkbpVD2NbAUa +klBRKHZm+UCJ8L6X4MgahNy+Y1uj6m14a50B9GtCi+RspP7p9pNKx9hnA8+dRs6Q +9oZgim2zMwvVBQIDAQABo2AwXjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAdBgNV +HQ4EFgQUQGqZ5v4NSB5Iwo17DynPRufgbF0wJQYIKwYBBQUHAQ4BAf8EFjAUAgEA +MA8GCCsGAQUFBxUABANmb28wDQYJKoZIhvcNAQEFBQADgYEAxQjN9RrCdZHhGAyS +y3/1EAyWIvmz8wKW0q4kSfNV7DAcUCKmQQ45oCEVnyTEbP8ltdIaHyIK1ujxKQC1 +QLDzjHkBBQGBrCH+gyIdpT9OZu2gT8f2j4u01YwbjLTcU2yEXVkkH18SZiawq2DF +ETkEd/u6TKzhpwFPuZPKUeFexPA= +-----END CERTIFICATE----- diff --git a/crypto/heimdal/lib/hx509/data/proxy-level-test.key b/crypto/heimdal/lib/hx509/data/proxy-level-test.key new file mode 100644 index 0000000..c697b1b --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/proxy-level-test.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQC0hrvRoael03J8Y5gvtDMq0ZGm5ZZMOGOhTtMnNlCpA/OKEpwM +PIxiWr625wFwD7YUupvUZ7qLodf5yTN1wkbpVD2NbAUaklBRKHZm+UCJ8L6X4Mga +hNy+Y1uj6m14a50B9GtCi+RspP7p9pNKx9hnA8+dRs6Q9oZgim2zMwvVBQIDAQAB +AoGBAI7cPM/1ZK1W+rezPSErMn7FH8V61Ij26ukhbvoOAqDuLpFqjrEkTVgcReaK +QtoCpO4ciur5N2f+qOLUNXQQTXpMN+nRxkKxLMhG99Hej+vmzPjMdimEtTJiRfKF +KU4rKUOCPdmu9fMe/kniOKbDmq1FFP+SqCU4hRiZZv0GMdDhAkEA8I6Du8UvTZ8I +04o05s/BlMiErASTZgq27UM6rWl2FNy5Av2suayBW7xJczdGEtbT982KwQmk0Mg9 +Hj5pWi5MDQJBAMAdorBVTMD4iFvfRhN6aSD3PzG/fsEexRuxvx2iBrrMZQ+6mS26 +8myNHPMASAiwt5H2T7Y/dNMB64iod5gFVtkCQDMJ+ddQKg4tDQFdFIZYVDlOJiAd +RGzlHxTOK9f5RU19219QFWK7wCKHm4nvk1WR8R1lpef5NNf7dERDd7Tjl80CQAx6 +oFO15rtuKWVWVnXzcJq8lLVFjBU9S25mGFTzbl554mKoK0UGLLMSY3wBW6x81h+8 +ESd0bcE7EbKZxtLwHdkCQQDYB5HxhlPZdquY+yg7vqxUF9Lf6+smlVv3PjfhXztg +2aV717UGinyqZgcn2J+ADWocRI3JnOhU0lswsGc+oVXp +-----END RSA PRIVATE KEY----- diff --git a/crypto/heimdal/lib/hx509/data/proxy-test.crt b/crypto/heimdal/lib/hx509/data/proxy-test.crt new file mode 100644 index 0000000..d0d3135 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/proxy-test.crt @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICMDCCAZmgAwIBAgIJAI8UaHGQmUvNMA0GCSqGSIb3DQEBBQUAMCExCzAJBgNV +BAYTAlNFMRIwEAYDVQQDDAlUZXN0IGNlcnQwHhcNMDcxMTE1MDY1ODU5WhcNMTcx +MTEyMDY1ODU5WjAxMQswCQYDVQQGEwJTRTESMBAGA1UEAwwJVGVzdCBjZXJ0MQ4w +DAYDVQQDDAVwcm94eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzeKelgMO +dEHFmfEANkv6k+HkOduzT2It++ma7Kg+6+eOWpBqWcY3AOEbSE2UJM6H+StDhNNS +cldPd3LoZayywckvgD3/NZjB9drsxF9GGClHew+fKjiekjNR3aUuAjysJYfr9AYd +E6AFft2qKphuPKlEjPDeOZ4RpjvQOgFRB28CAwEAAaNgMF4wCQYDVR0TBAIwADAL +BgNVHQ8EBAMCBeAwHQYDVR0OBBYEFOGuL3xdInqdArsxly/BbLmYbzDTMCUGCCsG +AQUFBwEOAQH/BBYwFAIBADAPBggrBgEFBQcVAAQDZm9vMA0GCSqGSIb3DQEBBQUA +A4GBADOZurVQ/lXeLADFOZbTmbRt0Nv3aPHniG1yovlSDEuNjMczeRMMIsef+jpJ +4Z0rt65i3qpX3uXZdCgGtIbusIlM7fBLCRI5vJ27jqs2PnCvodWO05e/aL3XxRwr +42wDWTioZuGm8Sz4hpHv74Fz/7PgvZPMFSo15ujdOTWMXj08 +-----END CERTIFICATE----- diff --git a/crypto/heimdal/lib/hx509/data/proxy-test.key b/crypto/heimdal/lib/hx509/data/proxy-test.key new file mode 100644 index 0000000..93b609b --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/proxy-test.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDN4p6WAw50QcWZ8QA2S/qT4eQ527NPYi376ZrsqD7r545akGpZ +xjcA4RtITZQkzof5K0OE01JyV093cuhlrLLByS+APf81mMH12uzEX0YYKUd7D58q +OJ6SM1HdpS4CPKwlh+v0Bh0ToAV+3aoqmG48qUSM8N45nhGmO9A6AVEHbwIDAQAB +AoGAaAv+2RDyXQ5gLkv9L3N2TwX5sMO2+odDdeu4v6DHK7D54ArbtELXyTn577BF +DdTSIroahSXGpMI7BsKrb7a3Hw+lnbEsag0a71yMM+E/zN9e0BgZwb7ZpeezVG2O +kaXCuVPQlmDys8UH001FWP/XxqhLfCjy25ynaXi990k0AwECQQDwI64IquGE0OCO +bI15Z+qLM5aRQgkNPokU7bZ1oSp9Ctx0pI9IzN6DcXe1QcXBDUJrZ0medNmNjqkG +KPkiAieDAkEA23vDr6+iiSTOIUAGj+NDY9ydk48j8oWYUeQPL8Y7hJrckJrqqfNL +MGZUKnF/RFPRbfS543xiqlXs4j3C61cwpQJAS9DH+l6Q8tDLhMvK4sCnMSmpaNTz +bKYIu33NdFfcxTuvnHfz8OUVf2RMigJo/+lCxgwHFysHIIUg4hv/g/gwJwJBAIfx +UHMwxetL8KCHl4jnqoXfz3nl3s4IESAnsYBVt+eaQ6MNUOuS1a9UsizXv4wCnmUM +f1Z3ZGU8c0xuFJzPlEECQAs9UM+v0WxhUY8iVltgaLxGP282Mg+p+pIoqXbn8Mt7 +gOomlisP+s0Hh+c+YFPIAaAeH6j7n4AxydI0Z9fKIZA= +-----END RSA PRIVATE KEY----- diff --git a/crypto/heimdal/lib/hx509/data/proxy10-child-child-test.crt b/crypto/heimdal/lib/hx509/data/proxy10-child-child-test.crt new file mode 100644 index 0000000..95abe01 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/proxy10-child-child-test.crt @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICdDCCAd2gAwIBAgIJAN27BSQHOOO6MA0GCSqGSIb3DQEBBQUAMEMxCzAJBgNV +BAYTAlNFMRIwEAYDVQQDDAlUZXN0IGNlcnQxEDAOBgNVBAMMB3Byb3h5MTAxDjAM +BgNVBAMMBWNoaWxkMB4XDTA3MTExNTA2NTkwMFoXDTE3MTExMjA2NTkwMFowUzEL +MAkGA1UEBhMCU0UxEjAQBgNVBAMMCVRlc3QgY2VydDEQMA4GA1UEAwwHcHJveHkx +MDEOMAwGA1UEAwwFY2hpbGQxDjAMBgNVBAMMBWNoaWxkMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQCw3LymYPXq7FKF1yumUvZTEbyMNszUYmoaMXgfnOgu8TWR +Dwek7ome68yHYYkc4fj1jG2ugdQ+/LgpJ10c+lHa1MeE7QHbJu6tNhRcCgxnAtlV +JljkmB24Ne/UjQwVVT73rUrvaigby8Ai0ujDtPJDqfUQvh8lwEFFWuafq9Ms1wID +AQABo2AwXjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAdBgNVHQ4EFgQUNBaggvaD +C/Amnb2M8g60WKxwGn0wJQYIKwYBBQUHAQ4BAf8EFjAUAgEKMA8GCCsGAQUFBxUA +BANmb28wDQYJKoZIhvcNAQEFBQADgYEAmT5WYZ6FM6ceyyxTKiusYLDPJ04D7dVk +VVMnu1q9dATMje/RKrncT0+KNEMdLWLpZgeHj4E2bi1507l3/zOUwOPpdI9MrvpY +Or6ssQ3sZAZI60ruZ91ml6cYt+rbE1F2J+y1CM0rW/wnAIT1v2vP2Wd7PrEm8RsM +QGbyuzcrAL4= +-----END CERTIFICATE----- diff --git a/crypto/heimdal/lib/hx509/data/proxy10-child-child-test.key b/crypto/heimdal/lib/hx509/data/proxy10-child-child-test.key new file mode 100644 index 0000000..247f616 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/proxy10-child-child-test.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQCw3LymYPXq7FKF1yumUvZTEbyMNszUYmoaMXgfnOgu8TWRDwek +7ome68yHYYkc4fj1jG2ugdQ+/LgpJ10c+lHa1MeE7QHbJu6tNhRcCgxnAtlVJljk +mB24Ne/UjQwVVT73rUrvaigby8Ai0ujDtPJDqfUQvh8lwEFFWuafq9Ms1wIDAQAB +AoGAHRo1cKtDzARXD+74H8ZHAiRJAkmCKvCGxQie25TWH+NRDS2L9HfL7XqfjSdf +iIEmlkElSzHR2wt6wkrX54zJKxMNayc88UfInQ03a4XwFzAksTf05zpdGPbkKohi +eeQcf3Raq+Swe4pTEwyEU8mDidM/rKJst+zMiE4UMeVGTQECQQDZPFrVTyJwGBcS +sxJly0zXmZ8tvvsxIuplwAvbfCWbhEEgeO3LAKjcpb5HVOLfTe8+2ZO00ALidVCH +N6/ae+iLAkEA0GwPxjlbKnL1VcpKdsegntACxlHD0TonvIEINKv9PiKzHIhQo8xJ +Rt/2aBRAOJn+zB3FJxfQ+o6vEUwvBfEKZQJBANHMLTlG9M5nJZlkogb3YZ3y+j0W +7cdVniRoZcsySau4/aDbyWO9nleCJpMDUxwwSzdasAD2x2JnxD7itA4AjuMCQQCP +a+0m8M0lVtowYPYA6rpCzs05/4YKckRp2Tj2Vev8WBB87+jd7nP2S6PaVyUiTgYi +G9JRZnguEwWxl4U8R3RpAkA5QpGHFhXNI2xA0ZKYH1tgmYfLBAAiVrIDKJddtOf/ +rKceL88RXsjnA6PTN9AdpnJ4sTToR3HDeEwAQrNHMC2M +-----END RSA PRIVATE KEY----- diff --git a/crypto/heimdal/lib/hx509/data/proxy10-child-test.crt b/crypto/heimdal/lib/hx509/data/proxy10-child-test.crt new file mode 100644 index 0000000..c450741 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/proxy10-child-test.crt @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICVDCCAb2gAwIBAgIJAITDCg/e+gWyMA0GCSqGSIb3DQEBBQUAMDMxCzAJBgNV +BAYTAlNFMRIwEAYDVQQDDAlUZXN0IGNlcnQxEDAOBgNVBAMMB3Byb3h5MTAwHhcN +MDcxMTE1MDY1OTAwWhcNMTcxMTEyMDY1OTAwWjBDMQswCQYDVQQGEwJTRTESMBAG +A1UEAwwJVGVzdCBjZXJ0MRAwDgYDVQQDDAdwcm94eTEwMQ4wDAYDVQQDDAVjaGls +ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAroEn/MX0t84+NLivDSbN0y5r +ZRxaiTDYkmvbdvJuBryCCLkzUT+/eh3pEK52BODXZWD4oiEMJLubH/pz+/6eAb4T +ReAWft/wMFaOSZ37a7iLWr8vFaRfBjQREpEm0rCp7dPvWYrraRIIjMRJzAUwygXN +KSS4f5VZkMwNfT9wwE8CAwEAAaNgMF4wCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAw +HQYDVR0OBBYEFJrcQRDczQ1P+84ND71GVT99a/2mMCUGCCsGAQUFBwEOAQH/BBYw +FAIBCjAPBggrBgEFBQcVAAQDZm9vMA0GCSqGSIb3DQEBBQUAA4GBALIbzPSyUE5Q +4TWAUfATVsADj131V1Xe+HHgwXebWbnNCJIe3OyWoFqK3X5ATKzi6MzHzA+UngFK +KGl8m8Ogx9dYQKzP2LIw0GuvpMyc3azb/cvbWv3vmM55UEdBlqxSTFynqLdpJqtn +9dXq2wCNdUtbGEOpaRVOiZ0wjvpTB4wA +-----END CERTIFICATE----- diff --git a/crypto/heimdal/lib/hx509/data/proxy10-child-test.key b/crypto/heimdal/lib/hx509/data/proxy10-child-test.key new file mode 100644 index 0000000..70cea5d --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/proxy10-child-test.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQCugSf8xfS3zj40uK8NJs3TLmtlHFqJMNiSa9t28m4GvIIIuTNR +P796HekQrnYE4NdlYPiiIQwku5sf+nP7/p4BvhNF4BZ+3/AwVo5JnftruItavy8V +pF8GNBESkSbSsKnt0+9ZiutpEgiMxEnMBTDKBc0pJLh/lVmQzA19P3DATwIDAQAB +AoGAaYkc+Odzd9IYluP2ojqMkiJpuu2p53yODgeC4+38EsDg14vB+GpYT+9U68zG +/W5JdjtuQwc/g9ueFnnuuUEkpyMIKDdAl00ZJQU5Vvz+ooZdxp/iYm3axkV2Gc2l +mbulzUxgpomflDd/B3RXO1jY4ZttpVHTNUvjm7DtypiqsAkCQQDgIIRBtSipM3F6 +GYKgnmsjK+19YxUdMbHS6fyfg0TDIrSrBi5EqyjgA4MzxfzimvfKCiV6SSqFnU3G +MIWDLh2dAkEAx1IaAAi+DmED08rarKRU2Ma7KRQWlxjXTp6c9OrbzuCJrqZgscxJ +vBjmHzbXCKumRZwqWgzM5mRxPVX6npyn2wJBALrWQIqqI3hRuzJnG78b8QJD91nE +hHBu4eeKSZ8MBgGJ6AR+RYnXCV8dbn11eifJufECXlW/sqPqC1DBWDuP8P0CQFxg +utglNSCo6gMw0ySMjR5jDL8/JjElPDSd4pTIfNNm0aj2R35f9hSNXao92m+UTl2Y +wTA3Gof1KV6KCLuWU10CQCeGYU3SFAy5QLVqR0B0u19wWyS8ZMl06DjOslmu7Zp+ +x1GxxFu1MNFvcKwmFeeYcNU1t9X0tC7EhUIaLQk2kqM= +-----END RSA PRIVATE KEY----- diff --git a/crypto/heimdal/lib/hx509/data/proxy10-test.crt b/crypto/heimdal/lib/hx509/data/proxy10-test.crt new file mode 100644 index 0000000..331c3ea --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/proxy10-test.crt @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICMjCCAZugAwIBAgIJAI8UaHGQmUvPMA0GCSqGSIb3DQEBBQUAMCExCzAJBgNV +BAYTAlNFMRIwEAYDVQQDDAlUZXN0IGNlcnQwHhcNMDcxMTE1MDY1OTAwWhcNMTcx +MTEyMDY1OTAwWjAzMQswCQYDVQQGEwJTRTESMBAGA1UEAwwJVGVzdCBjZXJ0MRAw +DgYDVQQDDAdwcm94eTEwMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDTeTGh +PIY39c75rcek77oZeDKnvO9zmsU2nlPnKpNsQ/QYEa610EeaRhB36lLhIS3aEtoG +LKgHeDF+jxasog3GNWZ7/EF5x5VwIbXo659ZbDwnT8c8ZJADEe1kfMuFgKd49l4y +PNCqN4LX2DdAh2HIb7x1iw7Fnu7s0Xnipgq0twIDAQABo2AwXjAJBgNVHRMEAjAA +MAsGA1UdDwQEAwIF4DAdBgNVHQ4EFgQUe24gc/gLyB6DW4gELVL3axuZTbkwJQYI +KwYBBQUHAQ4BAf8EFjAUAgEKMA8GCCsGAQUFBxUABANmb28wDQYJKoZIhvcNAQEF +BQADgYEABlvvmLwl6ZjaLdTGmxDD2eHN4/IbjYj1Vta2zQOKKA/W4qrkhmSNpy0x ++v9tqf2fumNSpspqF+g814pXbqSMuObHEE1IeUmiGwVPC7AMWVXd2skMdkjEqhLM +8qvDrPt+c5rGnnqM9AqrT/xDgXm7XnPLSFcrX/q8xVKVztskgEU= +-----END CERTIFICATE----- diff --git a/crypto/heimdal/lib/hx509/data/proxy10-test.key b/crypto/heimdal/lib/hx509/data/proxy10-test.key new file mode 100644 index 0000000..3bc0b45 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/proxy10-test.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXwIBAAKBgQDTeTGhPIY39c75rcek77oZeDKnvO9zmsU2nlPnKpNsQ/QYEa61 +0EeaRhB36lLhIS3aEtoGLKgHeDF+jxasog3GNWZ7/EF5x5VwIbXo659ZbDwnT8c8 +ZJADEe1kfMuFgKd49l4yPNCqN4LX2DdAh2HIb7x1iw7Fnu7s0Xnipgq0twIDAQAB +AoGBANDEIiSklXQFLFD8J81CBBxEtu007cbYkbx7zSS2uVb2NrDUM/+1IBrC9FsN +bshlctiIJ8hUqYTGOUZRh/bg/GpVOgTRAgaMBEBOYXra7r7TVcUUxpC8CzX9hevl +H42T6Ez6+Ednfg0RX6rZTiFeCNV3ADkguO07mlgSppiQJmlxAkEA/ICw/Ar/GtJH +/EK8jrbxzakNzFxtHUtVNwSALsiWZUfJWJgf7jDsl0XB8w/HhVDrdwfc+Aiexxc9 +SPJKKqdpswJBANZnBfxEucE1SWu9elvPNWIMYBXinfMvfnkSt81KH3AfObiUj93d +LCii1sF/x2aDeKJseFiUycy9xQXhQMF5vu0CQQCPECs24tQfUj1PBFDpW2YtbDdR +Lpz0GBa0EWy/FQ+BWucNt0OAJWAnZXK6UJpvQqXmzyG3tsqfat9iUUUMXcZZAkEA +vc+PePrPCMHIMl4ZCVa0iA00s6tg8n7FlSKBHnnUw0qhq0u64kyAX6lqPvyE57jU +/9bP5Hw0+9G1r7LvxVmnMQJBAMdphUdEYRlIZ0GTnIETDzjm3lge06cXzLvXFIps +nCANLV4OXJZVaTUrnDINLJVHu5d+Mx1pTw6GOF+v0+LjbF4= +-----END RSA PRIVATE KEY----- diff --git a/crypto/heimdal/lib/hx509/data/revoke.crt b/crypto/heimdal/lib/hx509/data/revoke.crt new file mode 100644 index 0000000..0adcc2d --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/revoke.crt @@ -0,0 +1,53 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Nov 15 06:58:56 2007 GMT + Not After : Nov 12 06:58:56 2017 GMT + Subject: C=SE, CN=Revoke cert + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b3:24:de:14:fc:b6:80:e2:34:59:81:1f:ec:cb: + 00:21:75:e5:34:88:09:5e:5e:8e:f8:91:6b:ab:09: + 34:f8:6c:69:14:00:c5:47:f2:d7:de:a0:32:00:02: + 63:79:3c:14:1a:a9:4d:d1:1d:c0:fc:a7:50:72:26: + 96:53:d1:9f:a9:5f:f4:82:4d:4b:17:3b:fe:14:60: + 42:94:22:93:3e:c5:14:97:c8:a3:6a:8e:bd:90:03: + 22:12:9e:41:ca:a5:de:4f:57:f4:bf:f1:9e:f8:63: + 4f:c0:9e:c8:3c:e1:8b:89:60:3a:2b:5c:a7:b7:6e: + a0:48:34:49:58:61:a0:34:6d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + F3:E2:96:20:28:53:21:92:67:A8:5C:B5:2C:7E:87:CF:7A:07:3D:84 + Signature Algorithm: sha1WithRSAEncryption + 90:39:f3:a6:fe:92:b9:92:4c:75:58:b2:51:36:11:07:f5:a2: + 71:dc:90:d7:2b:b5:bc:37:c8:30:4f:a4:6b:41:11:63:3e:53: + 42:ae:6f:59:7d:f8:b0:59:01:2f:50:4f:2d:21:7e:6a:58:bd: + 74:f1:69:c5:62:3d:8f:fa:1a:c8:7e:a4:30:dc:01:8b:c9:f8: + 77:44:5c:d3:a4:ab:9a:50:cc:45:d0:65:00:5c:fe:d3:b5:a3: + 7a:f1:b1:5c:25:0f:06:16:5f:cf:e2:5d:0b:87:c0:fe:14:b8: + 0a:10:17:55:34:15:4d:44:6b:60:80:6e:af:7b:81:30:47:5c: + f3:fe +-----BEGIN CERTIFICATE----- +MIIB/DCCAWWgAwIBAgIBAzANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMB4XDTA3MTExNTA2NTg1NloXDTE3 +MTExMjA2NTg1NlowIzELMAkGA1UEBhMCU0UxFDASBgNVBAMMC1Jldm9rZSBjZXJ0 +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzJN4U/LaA4jRZgR/sywAhdeU0 +iAleXo74kWurCTT4bGkUAMVH8tfeoDIAAmN5PBQaqU3RHcD8p1ByJpZT0Z+pX/SC +TUsXO/4UYEKUIpM+xRSXyKNqjr2QAyISnkHKpd5PV/S/8Z74Y0/Ansg84YuJYDor +XKe3bqBINElYYaA0bQIDAQABozkwNzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAd +BgNVHQ4EFgQU8+KWIChTIZJnqFy1LH6Hz3oHPYQwDQYJKoZIhvcNAQEFBQADgYEA +kDnzpv6SuZJMdViyUTYRB/WicdyQ1yu1vDfIME+ka0ERYz5TQq5vWX34sFkBL1BP +LSF+ali9dPFpxWI9j/oayH6kMNwBi8n4d0Rc06SrmlDMRdBlAFz+07WjevGxXCUP +BhZfz+JdC4fA/hS4ChAXVTQVTURrYIBur3uBMEdc8/4= +-----END CERTIFICATE----- diff --git a/crypto/heimdal/lib/hx509/data/revoke.key b/crypto/heimdal/lib/hx509/data/revoke.key new file mode 100644 index 0000000..a4c68ae --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/revoke.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQCzJN4U/LaA4jRZgR/sywAhdeU0iAleXo74kWurCTT4bGkUAMVH +8tfeoDIAAmN5PBQaqU3RHcD8p1ByJpZT0Z+pX/SCTUsXO/4UYEKUIpM+xRSXyKNq +jr2QAyISnkHKpd5PV/S/8Z74Y0/Ansg84YuJYDorXKe3bqBINElYYaA0bQIDAQAB +AoGAIDHl/5uTKQJ+Kf+8vw+UjG7lrFUuadlQlHd+BBT5ghPppoCk89M+3HGpyrqj +KeyUKF5477YLMtzW5kztA09PBBJvMjSm92dI2uCYfipkIWZZUlq64AStI15pgeVd +cH61hxOUCm47tqhtkaO11DnKkoJBXaAVIe2ySG2sIZQH+gECQQDjhMdCWkaO+HUe +utqKJCq6pUkwSelgLEINDVoRVgJ+qUHb0nN06DmPfcfxwqfgP/vS6baKkGIBCiZJ +n9Kfd23BAkEAyZHXY5iGSq9qc2ern0CcyitNozvtm6eEZYVvJxVMsVBQRo23EmGF +68SJlHjpY+nHyPWEkbG99R/CMdr3FV9JrQJBAOG/hoKk1mvXxUYXeu4kkq0dgXBD +diex4lvXCq423ETXJny55UtzfGGPGUwdq7rLYc/VjAUS29tSOclFppQJyUECQQDA +J7P5UhHTaN5GHfJR4rqVUCq3Dg45cLyaO1X3ICr4bePZHogDkcylMbsmOw3jHZ5D +SSqT6al44Em0VVVunmQRAkBUAQzHGGJnMKI9ZSdD3J6scWCVIjHVgaehYe9a8DlK +DeZ4KYGG0+1aUdkqeYE8c6Qqp+pdjPmRMdooww6y+Xk1 +-----END RSA PRIVATE KEY----- diff --git a/crypto/heimdal/lib/hx509/data/sf-class2-root.pem b/crypto/heimdal/lib/hx509/data/sf-class2-root.pem new file mode 100644 index 0000000..d552e65 --- /dev/null +++ b/crypto/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/crypto/heimdal/lib/hx509/data/static-file b/crypto/heimdal/lib/hx509/data/static-file new file mode 100644 index 0000000..2216857 --- /dev/null +++ b/crypto/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 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@" + +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/crypto/heimdal/lib/hx509/data/sub-ca.crt b/crypto/heimdal/lib/hx509/data/sub-ca.crt new file mode 100644 index 0000000..6cb485a --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/sub-ca.crt @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 9 (0x9) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Nov 15 06:58:59 2007 GMT + Not After : Nov 12 06:58:59 2017 GMT + Subject: C=SE, CN=Sub CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f3:ab:db:06:fa:f9:a1:84:35:a6:fb:a4:a9:39: + 5f:54:10:a2:a4:3f:1a:ae:2c:7e:bd:dd:aa:63:4a: + 7a:62:99:07:25:af:eb:62:b4:20:93:67:46:59:b4: + 30:85:81:24:41:9d:49:97:fb:a3:ce:74:61:f7:ff: + d5:9e:b1:9b:d3:5a:8b:59:51:76:99:69:2a:73:02: + e9:2d:39:3f:21:b8:2f:f1:af:91:1f:f1:c3:e3:4d: + c0:e4:87:95:df:e7:d2:e7:27:a6:cd:c4:cf:97:e6: + b8:24:31:d1:66:d3:af:f8:06:8b:9c:81:bf:66:54: + 53:08:0a:ee:15:71:b2:a5:a5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 36:04:CF:AD:8B:30:E2:5D:C0:43:8C:09:0B:4D:50:7B:1F:39:41:17 + X509v3 Authority Key Identifier: + keyid:8C:E7:0D:B5:C5:DE:69:85:75:2C:08:A1:DE:53:15:30:9C:A1:E8:00 + DirName:/CN=hx509 Test Root CA/C=SE + serial:B7:94:5E:85:B2:19:80:58 + + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment, Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 5b:f9:bb:2c:d2:d6:4d:bb:20:b1:05:fc:67:45:de:9c:5e:83: + 35:24:9a:f6:33:bc:3d:ca:27:dc:be:3c:cb:c6:d7:c5:b4:d3: + 9e:c4:c2:60:4d:dc:21:2c:f4:88:ec:dd:41:37:58:63:45:d6: + 9b:32:7d:f8:e0:d1:41:0f:f3:30:20:7d:15:af:49:15:2b:cb: + db:fe:90:6e:db:84:fa:92:a3:ac:83:25:5a:ab:49:7a:1e:2b: + dc:c9:74:7b:9f:2b:62:a9:6f:ef:b9:89:72:4b:ea:02:5a:27: + 93:b7:9d:fd:e2:a3:73:04:52:d0:98:5a:a3:23:f5:02:56:b6: + c6:8f +-----BEGIN CERTIFICATE----- +MIICWDCCAcGgAwIBAgIBCTANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMB4XDTA3MTExNTA2NTg1OVoXDTE3 +MTExMjA2NTg1OVowHjELMAkGA1UEBhMCU0UxDzANBgNVBAMMBlN1YiBDQTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA86vbBvr5oYQ1pvukqTlfVBCipD8arix+ +vd2qY0p6YpkHJa/rYrQgk2dGWbQwhYEkQZ1Jl/ujznRh9//VnrGb01qLWVF2mWkq +cwLpLTk/Ibgv8a+RH/HD403A5IeV3+fS5yemzcTPl+a4JDHRZtOv+AaLnIG/ZlRT +CAruFXGypaUCAwEAAaOBmTCBljAdBgNVHQ4EFgQUNgTPrYsw4l3AQ4wJC01Qex85 +QRcwWgYDVR0jBFMwUYAUjOcNtcXeaYV1LAih3lMVMJyh6AChLqQsMCoxGzAZBgNV +BAMMEmh4NTA5IFRlc3QgUm9vdCBDQTELMAkGA1UEBhMCU0WCCQC3lF6FshmAWDAM +BgNVHRMEBTADAQH/MAsGA1UdDwQEAwIB5jANBgkqhkiG9w0BAQUFAAOBgQBb+bss +0tZNuyCxBfxnRd6cXoM1JJr2M7w9yifcvjzLxtfFtNOexMJgTdwhLPSI7N1BN1hj +RdabMn344NFBD/MwIH0Vr0kVK8vb/pBu24T6kqOsgyVaq0l6HivcyXR7nytiqW/v +uYlyS+oCWieTt5394qNzBFLQmFqjI/UCVrbGjw== +-----END CERTIFICATE----- diff --git a/crypto/heimdal/lib/hx509/data/sub-ca.key b/crypto/heimdal/lib/hx509/data/sub-ca.key new file mode 100644 index 0000000..070d21d --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/sub-ca.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDzq9sG+vmhhDWm+6SpOV9UEKKkPxquLH693apjSnpimQclr+ti +tCCTZ0ZZtDCFgSRBnUmX+6POdGH3/9WesZvTWotZUXaZaSpzAuktOT8huC/xr5Ef +8cPjTcDkh5Xf59LnJ6bNxM+X5rgkMdFm06/4Boucgb9mVFMICu4VcbKlpQIDAQAB +AoGBAIoiQmgSnrERYdjnjtDf1Uqyo4C4xUc3siGwJ4diET8TwRl8QNQTiOQHB7qS +i28jZopLwAyIerPvBhqwzUjJJqvu1z+5/MjwBJ/aonmJjJ9e3nqk/KE658xGg5E8 +V64DYRif0YboZEYJo5yzU9UEdEPI4zTyhFlR21TmOZkidnwBAkEA/IIRCcGs/FNR +q9tEW8ARK1DEeerXhoV9Xye9xYb5UNyH4f6J31NdkvYOMA4F0+0lKecaKmPtKsu7 +gQrFZYwt/QJBAPcKgUVOJox/s/o1PXRGjifl1haehcawWNLtN/UnFZcUKslyMkxh +qyCJJ0SuX7quQqy+++hFj/DwNdECaFRd0skCQBocdRiWL4Y0M3jbBrmaJexdwMN+ +tmTRvwItAOHBMFzdQSvsf2NZoo6E5Tiw6odcuYAYxsrlZGwNf0k7zOfQVB0CQQDy +GWdqZhY9JoFYuYhKRULXMtTGQgBUIUpLG5L1O6Ja9rafyLwmQqkUL5U+J61FI7XP +2TLCBDn2I1J6TGO2GmSRAkAIFsFpkrq4q+lbJ3Vr3UpfhRJsTVOD5SgZx1umn63l +jEz5/r4HCg/Q0/yiPiYaTHutfnsChg3/AfbmWcA6j4NU +-----END RSA PRIVATE KEY----- diff --git a/crypto/heimdal/lib/hx509/data/sub-cert.crt b/crypto/heimdal/lib/hx509/data/sub-cert.crt new file mode 100644 index 0000000..fe23a37 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/sub-cert.crt @@ -0,0 +1,53 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 10 (0xa) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=SE, CN=Sub CA + Validity + Not Before: Nov 15 06:58:59 2007 GMT + Not After : Nov 12 06:58:59 2017 GMT + Subject: C=SE, CN=Test sub cert + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:da:41:57:e1:62:23:1b:bf:ac:1c:a9:06:c8:98: + 77:38:dc:33:a3:03:c0:02:6d:d8:6d:68:95:b1:ea: + 60:c0:c2:96:23:34:91:fb:32:44:44:cd:72:40:5b: + a3:cf:57:94:3c:8d:a9:30:11:73:61:15:17:10:a6: + 17:7d:9d:27:f0:58:23:ee:a4:83:3c:b1:0f:20:0c: + a4:3d:01:ef:de:93:cb:b5:02:c1:1e:b4:54:35:6a: + 8f:55:7b:5d:76:0a:f9:6d:b1:31:25:4c:fb:e2:d6: + 6e:94:e9:8a:c4:cc:4e:28:6b:bd:4c:80:85:2c:87: + eb:31:88:6d:27:2a:d3:df:1f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + D3:5F:89:9B:31:E6:2A:E0:C6:64:27:9F:A4:E5:42:8C:70:99:96:25 + Signature Algorithm: sha1WithRSAEncryption + 34:f9:9f:c5:6f:44:55:6a:15:8f:51:ab:c1:44:18:0e:eb:9a: + d0:c4:64:ce:ab:24:2b:77:82:f3:88:e3:9e:1f:9c:8d:28:a6: + be:3d:d5:3e:5e:95:01:c8:b9:d4:e2:b5:17:06:1d:10:0b:a5: + 64:29:d9:45:b0:fd:16:ec:5d:3c:3f:58:55:25:90:d0:e4:4f: + 3f:9f:9c:5f:d5:1e:0c:73:a5:1a:7c:71:10:b5:a3:d5:fb:0f: + d3:de:fc:9a:06:bc:0b:8c:72:eb:bc:fc:d1:47:87:68:44:25: + 25:ab:51:e9:af:d8:9e:1b:04:f2:1c:4f:4c:27:a0:87:11:4a: + 69:67 +-----BEGIN CERTIFICATE----- +MIIB8jCCAVugAwIBAgIBCjANBgkqhkiG9w0BAQUFADAeMQswCQYDVQQGEwJTRTEP +MA0GA1UEAwwGU3ViIENBMB4XDTA3MTExNTA2NTg1OVoXDTE3MTExMjA2NTg1OVow +JTELMAkGA1UEBhMCU0UxFjAUBgNVBAMMDVRlc3Qgc3ViIGNlcnQwgZ8wDQYJKoZI +hvcNAQEBBQADgY0AMIGJAoGBANpBV+FiIxu/rBypBsiYdzjcM6MDwAJt2G1olbHq +YMDCliM0kfsyRETNckBbo89XlDyNqTARc2EVFxCmF32dJ/BYI+6kgzyxDyAMpD0B +796Ty7UCwR60VDVqj1V7XXYK+W2xMSVM++LWbpTpisTMTihrvUyAhSyH6zGIbScq +098fAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTT +X4mbMeYq4MZkJ5+k5UKMcJmWJTANBgkqhkiG9w0BAQUFAAOBgQA0+Z/Fb0RVahWP +UavBRBgO65rQxGTOqyQrd4LziOOeH5yNKKa+PdU+XpUByLnU4rUXBh0QC6VkKdlF +sP0W7F08P1hVJZDQ5E8/n5xf1R4Mc6UafHEQtaPV+w/T3vyaBrwLjHLrvPzRR4do +RCUlq1Hpr9ieGwTyHE9MJ6CHEUppZw== +-----END CERTIFICATE----- diff --git a/crypto/heimdal/lib/hx509/data/sub-cert.key b/crypto/heimdal/lib/hx509/data/sub-cert.key new file mode 100644 index 0000000..b9faa56 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/sub-cert.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDaQVfhYiMbv6wcqQbImHc43DOjA8ACbdhtaJWx6mDAwpYjNJH7 +MkREzXJAW6PPV5Q8jakwEXNhFRcQphd9nSfwWCPupIM8sQ8gDKQ9Ae/ek8u1AsEe +tFQ1ao9Ve112CvltsTElTPvi1m6U6YrEzE4oa71MgIUsh+sxiG0nKtPfHwIDAQAB +AoGBAMPvk4h4BNK9gTL9n2RoU+fM7+Jx1GeZ24llMbZWlmOWjRiv8joTx2wJEH+s +hWP32NF/z5qin/VQ7LL6mO4hLx8RbPysfZH2PGwGLBsL6yFKrpVLEb6Gze7bfaNC +Zxqz2zBaUup5IN5IoQbYmhYgo7h+uca2FKZMtWZlvxsNb22hAkEA/QCwdBhlf7w9 +BUWezxxm5o/laKhvP7RYem43eJNKj1tenB1MnbjM6R3Ckp0ykbKQIEL3mjTEUR+/ +31yfSjKRrwJBANzXRXmowoaKFrjkRFjfKrSk6cIa5/32U4Shy3/1LRoHv1qcsyEv +0Acn5aE8vdiYK4J/OqiS87KFYH6WISCEFZECQQDg4xH1wBHIfvwGiaHmGyrkWpfi +dYWdrKLRANNR3Cr0TpVEU07dC30o4YkoZY6jr4MpCh2o9qpiKcSVuHDmtRiFAkBE +AsvznqRhuK8su6fM0tWdElinHZAqpyyrYQSB4KjGJnKo3i9QXiArw/60/DbfOGXV +54bSGYeRh//inCuRjvvxAkBv9rarlopkpj29aAM4e4gs5W4ssl0uOjnSBiSH+Zn/ +j/oYrQgvpITFLCdF48D44GWtupw5zCLiJAREySaNma4Z +-----END RSA PRIVATE KEY----- diff --git a/crypto/heimdal/lib/hx509/data/sub-cert.p12 b/crypto/heimdal/lib/hx509/data/sub-cert.p12 Binary files differnew file mode 100644 index 0000000..90def93 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/sub-cert.p12 diff --git a/crypto/heimdal/lib/hx509/data/test-ds-only.crt b/crypto/heimdal/lib/hx509/data/test-ds-only.crt new file mode 100644 index 0000000..78559c6 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/test-ds-only.crt @@ -0,0 +1,53 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 5 (0x5) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Nov 15 06:58:57 2007 GMT + Not After : Nov 12 06:58:57 2017 GMT + Subject: C=SE, CN=Test cert DigitalSignature + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c7:40:d0:87:47:81:b2:4e:4b:36:7c:c9:8d:9d: + eb:dc:65:13:20:dc:72:0f:bf:5e:44:36:aa:18:fc: + 09:54:8c:1a:4e:15:5a:c5:c3:0c:95:f7:55:1c:b0: + 93:d2:80:92:eb:7e:67:b4:2e:9c:0c:fd:65:6a:9c: + d6:35:d2:c2:62:3f:a2:6c:90:9e:a6:5a:59:33:e1: + 3a:13:9a:9d:9a:7e:2b:a2:44:96:41:87:b3:e2:b8: + 62:1b:88:46:08:39:c5:7a:90:83:42:22:c9:73:9f: + 41:51:1d:40:34:0f:94:0e:2a:ee:27:76:6d:6d:44: + d2:e7:90:ad:9c:da:f8:7f:87 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation + X509v3 Subject Key Identifier: + B9:41:3E:C9:AB:F2:37:75:F1:F8:C7:86:BB:54:78:76:15:16:D9:BB + Signature Algorithm: sha1WithRSAEncryption + 72:fc:ea:ad:ec:08:be:45:34:5e:d0:1b:d0:0d:fc:2f:70:89: + 8e:58:fb:15:ce:7b:78:8f:db:e9:97:cc:89:10:e6:10:f5:22: + f9:e9:c6:0d:4e:f9:35:c6:e2:5f:ab:28:47:e3:d6:94:d0:80: + db:44:4a:a9:8b:86:8b:c6:09:7b:d5:eb:07:ef:92:5a:ac:9a: + a7:04:c5:e2:c5:3f:01:d0:c1:92:c1:14:90:50:bd:0f:38:09: + 0e:c5:9f:96:bd:42:8b:87:ac:b1:62:ca:bc:79:1d:fc:23:06: + 55:b3:55:f2:b8:49:67:8e:d7:63:1f:52:aa:b9:19:e0:1f:18: + 11:ac +-----BEGIN CERTIFICATE----- +MIICCzCCAXSgAwIBAgIBBTANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMB4XDTA3MTExNTA2NTg1N1oXDTE3 +MTExMjA2NTg1N1owMjELMAkGA1UEBhMCU0UxIzAhBgNVBAMMGlRlc3QgY2VydCBE +aWdpdGFsU2lnbmF0dXJlMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHQNCH +R4GyTks2fMmNnevcZRMg3HIPv15ENqoY/AlUjBpOFVrFwwyV91UcsJPSgJLrfme0 +LpwM/WVqnNY10sJiP6JskJ6mWlkz4ToTmp2afiuiRJZBh7PiuGIbiEYIOcV6kINC +Islzn0FRHUA0D5QOKu4ndm1tRNLnkK2c2vh/hwIDAQABozkwNzAJBgNVHRMEAjAA +MAsGA1UdDwQEAwIGwDAdBgNVHQ4EFgQUuUE+yavyN3Xx+MeGu1R4dhUW2bswDQYJ +KoZIhvcNAQEFBQADgYEAcvzqrewIvkU0XtAb0A38L3CJjlj7Fc57eI/b6ZfMiRDm +EPUi+enGDU75NcbiX6soR+PWlNCA20RKqYuGi8YJe9XrB++SWqyapwTF4sU/AdDB +ksEUkFC9DzgJDsWflr1Ci4essWLKvHkd/CMGVbNV8rhJZ47XYx9SqrkZ4B8YEaw= +-----END CERTIFICATE----- diff --git a/crypto/heimdal/lib/hx509/data/test-ds-only.key b/crypto/heimdal/lib/hx509/data/test-ds-only.key new file mode 100644 index 0000000..1233c34 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/test-ds-only.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDHQNCHR4GyTks2fMmNnevcZRMg3HIPv15ENqoY/AlUjBpOFVrF +wwyV91UcsJPSgJLrfme0LpwM/WVqnNY10sJiP6JskJ6mWlkz4ToTmp2afiuiRJZB +h7PiuGIbiEYIOcV6kINCIslzn0FRHUA0D5QOKu4ndm1tRNLnkK2c2vh/hwIDAQAB +AoGAPa3Ln0S8WjSwRaKlRahP/b5wCGkVCdjkVltRlkBWpwxjjC5CFhvFxpp0h1gF +ulDAqhNMCNOwzLiX70Ozb5/ZOcK6eIYolFDf8ldc5fSJMTIZF2V6CzICNNKFGWpI +z5QFhfQDqru6ZaWtPuK4sJIcmBx1nMTu4z9rNjvnGqJV/ckCQQDm8HfOI6f5Dlgg +QI9My7uDshfF2j6lo8wX32Vsgfb2PO+a6BGCCQhSjlKSZoiOH+KNz1/fp0/sbeGY +ZbdJSMg9AkEA3OAZrLlgKId6Gs5EjDfvq2njJf4dAOk5aH8HB1u18VuRvdkWxEwo +A7zrFZz+l1U52OMNKazPuPLju7foen9fEwJAR1URfG/RC4HdwKCQYsUvN1+ELk3a +OemdOeZ7+ocuVCLAU9XIyqSlmHJzmNro5RV+MhVS5M9WRY4vN5Z7hbxgdQJBAJG3 +NrkAwzN5zVCJ7Cclb/SCMt0JvFCxjLInu5dbJblJU+kPozl1lKCCrgTgQgXMsBEq +GbD41UGK3DsnpTPLfAkCQQCeZlgPiddfNhyg3SQOgj1M/3NBEfJFnX3FqlF32Pvz +0U29o0iMSP4q2j+cyUxAmlp9I7clhq7bBRTfCHKIHETg +-----END RSA PRIVATE KEY----- diff --git a/crypto/heimdal/lib/hx509/data/test-enveloped-aes-128 b/crypto/heimdal/lib/hx509/data/test-enveloped-aes-128 Binary files differnew file mode 100644 index 0000000..c706839 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/test-enveloped-aes-128 diff --git a/crypto/heimdal/lib/hx509/data/test-enveloped-aes-256 b/crypto/heimdal/lib/hx509/data/test-enveloped-aes-256 Binary files differnew file mode 100644 index 0000000..1d5ef41 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/test-enveloped-aes-256 diff --git a/crypto/heimdal/lib/hx509/data/test-enveloped-des b/crypto/heimdal/lib/hx509/data/test-enveloped-des Binary files differnew file mode 100644 index 0000000..85a08d9 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/test-enveloped-des diff --git a/crypto/heimdal/lib/hx509/data/test-enveloped-des-ede3 b/crypto/heimdal/lib/hx509/data/test-enveloped-des-ede3 Binary files differnew file mode 100644 index 0000000..deb5fe1 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/test-enveloped-des-ede3 diff --git a/crypto/heimdal/lib/hx509/data/test-enveloped-rc2-128 b/crypto/heimdal/lib/hx509/data/test-enveloped-rc2-128 Binary files differnew file mode 100644 index 0000000..ebe0b5f --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/test-enveloped-rc2-128 diff --git a/crypto/heimdal/lib/hx509/data/test-enveloped-rc2-40 b/crypto/heimdal/lib/hx509/data/test-enveloped-rc2-40 Binary files differnew file mode 100644 index 0000000..c664b81 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/test-enveloped-rc2-40 diff --git a/crypto/heimdal/lib/hx509/data/test-enveloped-rc2-64 b/crypto/heimdal/lib/hx509/data/test-enveloped-rc2-64 Binary files differnew file mode 100644 index 0000000..24bd368 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/test-enveloped-rc2-64 diff --git a/crypto/heimdal/lib/hx509/data/test-ke-only.crt b/crypto/heimdal/lib/hx509/data/test-ke-only.crt new file mode 100644 index 0000000..9239de4 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/test-ke-only.crt @@ -0,0 +1,53 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4 (0x4) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Nov 15 06:58:57 2007 GMT + Not After : Nov 12 06:58:57 2017 GMT + Subject: C=SE, CN=Test cert KeyEncipherment + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bd:6a:09:6d:65:fd:2f:a6:02:74:48:59:5a:d6: + b1:cf:d2:30:60:21:92:bf:ed:94:d1:df:e9:de:b7: + c2:c5:5d:c8:7b:a7:f2:b3:e0:1b:78:ba:a8:ba:4b: + ee:95:5c:06:77:10:39:be:e5:4c:4a:f0:1e:96:a0: + df:77:7a:7a:06:ce:95:b0:d9:fd:ac:4b:85:45:b1: + 7c:a5:51:af:b8:c3:82:6f:21:09:37:03:b0:61:e0: + 04:46:a8:71:56:a6:36:67:79:42:e1:ef:bf:28:1d: + a0:ef:02:6e:26:60:e1:fe:05:95:72:87:b9:c1:08: + 8e:ed:dc:fd:71:06:15:80:79 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 17:F3:F4:8B:D1:CD:D4:A3:D9:9D:A0:0E:6E:52:EE:11:03:85:32:6F + Signature Algorithm: sha1WithRSAEncryption + 5f:1d:86:c2:bd:eb:c7:75:ad:b6:ec:c8:10:96:4f:8b:b2:36: + b4:7b:ba:c4:b5:6c:1c:2e:80:eb:d0:97:5f:71:48:8a:79:f7: + 05:ee:2b:96:ef:b9:68:0d:fa:86:73:c7:30:3f:22:81:ea:cf: + 46:3a:4b:4d:31:39:29:5d:1a:b8:44:ae:12:f1:18:ea:de:55: + 47:f4:1c:77:07:34:41:cf:1c:f1:1c:f8:0d:63:c1:e8:b4:98: + e7:cb:c1:2d:96:b3:5a:21:6e:fa:e7:e1:15:87:84:c9:71:31: + 5f:6f:93:98:7f:ca:00:d3:8d:96:bb:b5:03:af:c0:4d:4e:a2: + a5:97 +-----BEGIN CERTIFICATE----- +MIICCjCCAXOgAwIBAgIBBDANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMB4XDTA3MTExNTA2NTg1N1oXDTE3 +MTExMjA2NTg1N1owMTELMAkGA1UEBhMCU0UxIjAgBgNVBAMMGVRlc3QgY2VydCBL +ZXlFbmNpcGhlcm1lbnQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL1qCW1l +/S+mAnRIWVrWsc/SMGAhkr/tlNHf6d63wsVdyHun8rPgG3i6qLpL7pVcBncQOb7l +TErwHpag33d6egbOlbDZ/axLhUWxfKVRr7jDgm8hCTcDsGHgBEaocVamNmd5QuHv +vygdoO8CbiZg4f4FlXKHucEIju3c/XEGFYB5AgMBAAGjOTA3MAkGA1UdEwQCMAAw +CwYDVR0PBAQDAgVgMB0GA1UdDgQWBBQX8/SL0c3Uo9mdoA5uUu4RA4UybzANBgkq +hkiG9w0BAQUFAAOBgQBfHYbCvevHda227MgQlk+Lsja0e7rEtWwcLoDr0JdfcUiK +efcF7iuW77loDfqGc8cwPyKB6s9GOktNMTkpXRq4RK4S8Rjq3lVH9Bx3BzRBzxzx +HPgNY8HotJjny8EtlrNaIW765+EVh4TJcTFfb5OYf8oA042Wu7UDr8BNTqKllw== +-----END CERTIFICATE----- diff --git a/crypto/heimdal/lib/hx509/data/test-ke-only.key b/crypto/heimdal/lib/hx509/data/test-ke-only.key new file mode 100644 index 0000000..878267e --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/test-ke-only.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQC9agltZf0vpgJ0SFla1rHP0jBgIZK/7ZTR3+net8LFXch7p/Kz +4Bt4uqi6S+6VXAZ3EDm+5UxK8B6WoN93enoGzpWw2f2sS4VFsXylUa+4w4JvIQk3 +A7Bh4ARGqHFWpjZneULh778oHaDvAm4mYOH+BZVyh7nBCI7t3P1xBhWAeQIDAQAB +AoGASR2vee1OqJ/6foyXAXuys7g9OD59eVzqf4Fhs7lXk/w5sZIJG+o8cIQNMayx +8jHNxRQcVlYI9zxtclOzL1m11FPRgP6oVicPdIbKf/9JQhjlq/RgX/N66iBSPOW3 +80RtZ0G9pI+9RQN3sG1t39sXyMZJz5ApkcrsIfkX7Ej8tAkCQQD1mqP32MjUIpDc +x15ybBXib7E/27f/aM04Zg4D1WLkYANmUKFLiNeKKEIy+R6iQ9bqcWdh/u2Pu08e +I9eusolbAkEAxW6GQOihK5hsmKY7QdrORP6I6g8nqu/esiN1/LMtIVZdHtuaLxea +3XUIewnK1h5d2eKXyWjMgT8o5y/XtT5xuwJAVW7mbJeHPGuNso7TZr/8WNj7cjgu +5/R/toehhmnazZAsfpG7mbfPKirY5DxOEKnCf6jVCnyQDHhejCBxrT5DkwJBALrW +MW7Tt1JOWNbM2V8k9fcM+fymgt+dSJ5EOK//0EGwPUeqgmr2Z7QTwQbO6YlgC2ja +qtILvxzA7LB78iKvCWkCQQCOPkDbIzy5JM8AZtUFYb7PqJBb5fHDg3wiKWXiTh8+ +eaBxDdbBxCsamPLwfP2cguCvVv9yz3ODA9Aopny9iAv3 +-----END RSA PRIVATE KEY----- diff --git a/crypto/heimdal/lib/hx509/data/test-nopw.p12 b/crypto/heimdal/lib/hx509/data/test-nopw.p12 Binary files differnew file mode 100644 index 0000000..49db084 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/test-nopw.p12 diff --git a/crypto/heimdal/lib/hx509/data/test-pw.key b/crypto/heimdal/lib/hx509/data/test-pw.key new file mode 100644 index 0000000..e844a98 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/test-pw.key @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,B9B1B14B38E4ED57E3F9D8DFA7FEB086 + +mgUkuZfb6TTZ+69kLKbHpwfSYmY1tRMeIuuqcY6qdNpF70kiZ6BylMYzGG29OZJQ +ttiYmYz1zFYVhWrnpGnK7Raa7CHaohlcPfiUBD2lRzNmj6xYAJdooiR9kWNnZZe5 +JTOpLuokpSWSqgS58AB1BLkK67JGTEhF3iDwPff/oVBjW5X/VMRd62RfDk32MJmd +nd+xNdBeKk7nXwMITZyv3n5KayVohNSpFblIAwl/k8BDLavIKboZtJDqw9LyRpWC +KLtToAWTO7pvZcOoK9yIhM5TtbZkp7pQrebGjoYkvdF84i4oVS85q8swwsw7BFq5 +s8AVbdC0kcj5tfSaJYxFonyj5BHiEc1k1CLkcn0Aff1DhW/vR93W28UgQBT11Lxf +bvHxCSIGp6TKut7Jr1FGs6tzU5eTI2AlWeWJBoANDD2HaKnouRQfDEf8pHP9Odxg +nOQ4HinpwpylimqisYqHbeocO5izz1xioze82SxYQTUGj+gCViSBIBesVaZ31DGm +3ECN94ItCm9z6zAeMNtUdLkTY6rPeetwrXXcrWddD7p5c1HdWEEQHU1HilunQc6N +I39udeWfW0HlINxKu7IgOepNipdw9EFUPtY1LGP+2Xa3ezi8saXPbsq0i/0looWf +dhjvWke/uwi16zwDKL25pNSmSAKyhD+P46f5pcf1yk1MbMkFbfTrHzcxOIN1Fd5m +rFVJTUnVonQinb8cEyqgg/2ufvOe6AnaIqjsKdFUQthYrCg6Voupis+SXRbIefhr +diiBsOoIu8O38I9R6KmSs+CYTBeChWmt1sAJudRIgZ3v5vTm734qwlxijL4sSkYQ +-----END RSA PRIVATE KEY----- diff --git a/crypto/heimdal/lib/hx509/data/test-signed-data b/crypto/heimdal/lib/hx509/data/test-signed-data Binary files differnew file mode 100644 index 0000000..ae27556 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/test-signed-data diff --git a/crypto/heimdal/lib/hx509/data/test-signed-data-noattr b/crypto/heimdal/lib/hx509/data/test-signed-data-noattr Binary files differnew file mode 100644 index 0000000..11b008e --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/test-signed-data-noattr diff --git a/crypto/heimdal/lib/hx509/data/test-signed-data-noattr-nocerts b/crypto/heimdal/lib/hx509/data/test-signed-data-noattr-nocerts Binary files differnew file mode 100644 index 0000000..0c94ab9 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/test-signed-data-noattr-nocerts diff --git a/crypto/heimdal/lib/hx509/data/test.combined.crt b/crypto/heimdal/lib/hx509/data/test.combined.crt new file mode 100644 index 0000000..05c1e74 --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/test.combined.crt @@ -0,0 +1,68 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Nov 15 06:58:56 2007 GMT + Not After : Nov 12 06:58:56 2017 GMT + Subject: C=SE, CN=Test cert + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e8:bd:c6:8e:de:37:d8:f3:43:23:c3:27:b6:49: + 65:33:a8:b2:a9:f0:16:0d:90:49:47:7b:90:98:e4: + ae:de:dd:64:b6:3b:48:b7:2e:0b:02:18:1f:85:f3: + 48:af:78:4b:54:34:63:62:06:30:f0:b5:a2:e9:db: + 35:6c:c7:55:f5:30:27:a0:66:54:a5:e8:52:27:52: + 43:4e:90:04:11:6a:e8:2b:52:e4:8d:fe:fd:c4:aa: + b0:4e:63:c6:aa:2d:0a:4e:1d:ae:1c:0d:c8:12:10: + 93:af:5c:e5:31:30:df:2c:0d:d7:c4:9e:d1:fd:37: + 3a:45:71:fa:62:af:90:5e:c3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + D0:9B:77:9A:88:C7:AD:71:07:17:56:E1:0C:4D:B2:23:85:81:D1:EB + Signature Algorithm: sha1WithRSAEncryption + 88:f8:ee:7d:35:36:1c:a9:71:e4:c5:64:b9:c9:c2:2d:9d:d5: + 79:67:25:12:d7:96:28:4c:dd:92:6a:19:6b:ce:bc:fa:78:bd: + f3:d2:c4:5c:a9:d9:4a:b7:ef:40:8f:c8:e2:1a:67:90:58:a4: + 71:76:87:c2:66:9e:69:57:37:c9:15:b8:c7:d9:fa:3f:32:be: + 14:5e:7b:41:5c:7f:c2:54:1b:f1:1b:15:20:8c:0a:62:7c:71: + 07:ff:7d:df:71:75:0c:4b:7d:b8:a1:59:e1:5a:4e:b7:c1:df: + 98:3b:cf:c9:de:e3:73:6f:fa:2d:fa:39:c5:59:92:08:c4:6b: + 43:7a +-----BEGIN CERTIFICATE----- +MIIB+jCCAWOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMB4XDTA3MTExNTA2NTg1NloXDTE3 +MTExMjA2NTg1NlowITELMAkGA1UEBhMCU0UxEjAQBgNVBAMMCVRlc3QgY2VydDCB +nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6L3Gjt432PNDI8MntkllM6iyqfAW +DZBJR3uQmOSu3t1ktjtIty4LAhgfhfNIr3hLVDRjYgYw8LWi6ds1bMdV9TAnoGZU +pehSJ1JDTpAEEWroK1Lkjf79xKqwTmPGqi0KTh2uHA3IEhCTr1zlMTDfLA3XxJ7R +/Tc6RXH6Yq+QXsMCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwHQYD +VR0OBBYEFNCbd5qIx61xBxdW4QxNsiOFgdHrMA0GCSqGSIb3DQEBBQUAA4GBAIj4 +7n01NhypceTFZLnJwi2d1XlnJRLXlihM3ZJqGWvOvPp4vfPSxFyp2Uq370CPyOIa +Z5BYpHF2h8JmnmlXN8kVuMfZ+j8yvhRee0Fcf8JUG/EbFSCMCmJ8cQf/fd9xdQxL +fbihWeFaTrfB35g7z8ne43Nv+i36OcVZkgjEa0N6 +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDovcaO3jfY80Mjwye2SWUzqLKp8BYNkElHe5CY5K7e3WS2O0i3 +LgsCGB+F80iveEtUNGNiBjDwtaLp2zVsx1X1MCegZlSl6FInUkNOkAQRaugrUuSN +/v3EqrBOY8aqLQpOHa4cDcgSEJOvXOUxMN8sDdfEntH9NzpFcfpir5BewwIDAQAB +AoGBAKS3WsVWBBRo5cVzorFh9FvBMuEOZ60lxpbunoF2p0RXT6WhA2+RCH1s8TJt +4a0956IqiYOgehaBllEHsSHRWcUZ0P96qhZbVn1fWem0/U1VGb6d9WFftqPCOgYI +0joyDn+mmS1nhILexQARULyM67JyhX1xVbgFQUeTtr2WGIdBAkEA9hQURHdgxsu+ +iqe+93I1mA0LccKI3Mmb9jM0DBW1+NeGw17xE39u2DTLsFTIXkcpGzbaJYPaaOhU +pcpLX7haMQJBAPIgCT9cwEhX/MQq4eViCXd7blg4FxlDJDrD8sC8E0xss2N9Kpk4 +aJBtd4leOlzDwCanlWHrMCKo/NuE2b58FzMCQQDLTMtxxS6vDqTc6LlctX6RoDVU +RuPLhMTVInhdg5JTg7xSrJ1+/kkVVojxpRnkyeWsFiUj2UsYYNmOHxMmgagBAkEA +1to8uoAolEmXn89Zsv3C3salzRzAyob84DS+9e4uxdNzf+Yy5dHbX8Xzm+8EpQqD +OQnekgxsI2WHM5h4zAI7ZwJAefxLT1ljFxZmp1612/jqDaeNmmUHIN2aMpDinIle +r2S7S+UC+m573YcLZoYy9QAcTjnvgs/99zXjewfIQSQOmw== +-----END RSA PRIVATE KEY----- diff --git a/crypto/heimdal/lib/hx509/data/test.crt b/crypto/heimdal/lib/hx509/data/test.crt new file mode 100644 index 0000000..607605b --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/test.crt @@ -0,0 +1,53 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=hx509 Test Root CA, C=SE + Validity + Not Before: Nov 15 06:58:56 2007 GMT + Not After : Nov 12 06:58:56 2017 GMT + Subject: C=SE, CN=Test cert + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e8:bd:c6:8e:de:37:d8:f3:43:23:c3:27:b6:49: + 65:33:a8:b2:a9:f0:16:0d:90:49:47:7b:90:98:e4: + ae:de:dd:64:b6:3b:48:b7:2e:0b:02:18:1f:85:f3: + 48:af:78:4b:54:34:63:62:06:30:f0:b5:a2:e9:db: + 35:6c:c7:55:f5:30:27:a0:66:54:a5:e8:52:27:52: + 43:4e:90:04:11:6a:e8:2b:52:e4:8d:fe:fd:c4:aa: + b0:4e:63:c6:aa:2d:0a:4e:1d:ae:1c:0d:c8:12:10: + 93:af:5c:e5:31:30:df:2c:0d:d7:c4:9e:d1:fd:37: + 3a:45:71:fa:62:af:90:5e:c3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + D0:9B:77:9A:88:C7:AD:71:07:17:56:E1:0C:4D:B2:23:85:81:D1:EB + Signature Algorithm: sha1WithRSAEncryption + 88:f8:ee:7d:35:36:1c:a9:71:e4:c5:64:b9:c9:c2:2d:9d:d5: + 79:67:25:12:d7:96:28:4c:dd:92:6a:19:6b:ce:bc:fa:78:bd: + f3:d2:c4:5c:a9:d9:4a:b7:ef:40:8f:c8:e2:1a:67:90:58:a4: + 71:76:87:c2:66:9e:69:57:37:c9:15:b8:c7:d9:fa:3f:32:be: + 14:5e:7b:41:5c:7f:c2:54:1b:f1:1b:15:20:8c:0a:62:7c:71: + 07:ff:7d:df:71:75:0c:4b:7d:b8:a1:59:e1:5a:4e:b7:c1:df: + 98:3b:cf:c9:de:e3:73:6f:fa:2d:fa:39:c5:59:92:08:c4:6b: + 43:7a +-----BEGIN CERTIFICATE----- +MIIB+jCCAWOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAqMRswGQYDVQQDDBJoeDUw +OSBUZXN0IFJvb3QgQ0ExCzAJBgNVBAYTAlNFMB4XDTA3MTExNTA2NTg1NloXDTE3 +MTExMjA2NTg1NlowITELMAkGA1UEBhMCU0UxEjAQBgNVBAMMCVRlc3QgY2VydDCB +nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6L3Gjt432PNDI8MntkllM6iyqfAW +DZBJR3uQmOSu3t1ktjtIty4LAhgfhfNIr3hLVDRjYgYw8LWi6ds1bMdV9TAnoGZU +pehSJ1JDTpAEEWroK1Lkjf79xKqwTmPGqi0KTh2uHA3IEhCTr1zlMTDfLA3XxJ7R +/Tc6RXH6Yq+QXsMCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwHQYD +VR0OBBYEFNCbd5qIx61xBxdW4QxNsiOFgdHrMA0GCSqGSIb3DQEBBQUAA4GBAIj4 +7n01NhypceTFZLnJwi2d1XlnJRLXlihM3ZJqGWvOvPp4vfPSxFyp2Uq370CPyOIa +Z5BYpHF2h8JmnmlXN8kVuMfZ+j8yvhRee0Fcf8JUG/EbFSCMCmJ8cQf/fd9xdQxL +fbihWeFaTrfB35g7z8ne43Nv+i36OcVZkgjEa0N6 +-----END CERTIFICATE----- diff --git a/crypto/heimdal/lib/hx509/data/test.key b/crypto/heimdal/lib/hx509/data/test.key new file mode 100644 index 0000000..5251ceb --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/test.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDovcaO3jfY80Mjwye2SWUzqLKp8BYNkElHe5CY5K7e3WS2O0i3 +LgsCGB+F80iveEtUNGNiBjDwtaLp2zVsx1X1MCegZlSl6FInUkNOkAQRaugrUuSN +/v3EqrBOY8aqLQpOHa4cDcgSEJOvXOUxMN8sDdfEntH9NzpFcfpir5BewwIDAQAB +AoGBAKS3WsVWBBRo5cVzorFh9FvBMuEOZ60lxpbunoF2p0RXT6WhA2+RCH1s8TJt +4a0956IqiYOgehaBllEHsSHRWcUZ0P96qhZbVn1fWem0/U1VGb6d9WFftqPCOgYI +0joyDn+mmS1nhILexQARULyM67JyhX1xVbgFQUeTtr2WGIdBAkEA9hQURHdgxsu+ +iqe+93I1mA0LccKI3Mmb9jM0DBW1+NeGw17xE39u2DTLsFTIXkcpGzbaJYPaaOhU +pcpLX7haMQJBAPIgCT9cwEhX/MQq4eViCXd7blg4FxlDJDrD8sC8E0xss2N9Kpk4 +aJBtd4leOlzDwCanlWHrMCKo/NuE2b58FzMCQQDLTMtxxS6vDqTc6LlctX6RoDVU +RuPLhMTVInhdg5JTg7xSrJ1+/kkVVojxpRnkyeWsFiUj2UsYYNmOHxMmgagBAkEA +1to8uoAolEmXn89Zsv3C3salzRzAyob84DS+9e4uxdNzf+Yy5dHbX8Xzm+8EpQqD +OQnekgxsI2WHM5h4zAI7ZwJAefxLT1ljFxZmp1612/jqDaeNmmUHIN2aMpDinIle +r2S7S+UC+m573YcLZoYy9QAcTjnvgs/99zXjewfIQSQOmw== +-----END RSA PRIVATE KEY----- diff --git a/crypto/heimdal/lib/hx509/data/test.p12 b/crypto/heimdal/lib/hx509/data/test.p12 Binary files differnew file mode 100644 index 0000000..ad3e90a --- /dev/null +++ b/crypto/heimdal/lib/hx509/data/test.p12 diff --git a/crypto/heimdal/lib/hx509/data/yutaka-pad-broken-ca.pem b/crypto/heimdal/lib/hx509/data/yutaka-pad-broken-ca.pem new file mode 100644 index 0000000..32685d1 --- /dev/null +++ b/crypto/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/crypto/heimdal/lib/hx509/data/yutaka-pad-broken-cert.pem b/crypto/heimdal/lib/hx509/data/yutaka-pad-broken-cert.pem new file mode 100644 index 0000000..b0726ea --- /dev/null +++ b/crypto/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/crypto/heimdal/lib/hx509/data/yutaka-pad-ok-ca.pem b/crypto/heimdal/lib/hx509/data/yutaka-pad-ok-ca.pem new file mode 100644 index 0000000..32685d1 --- /dev/null +++ b/crypto/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/crypto/heimdal/lib/hx509/data/yutaka-pad-ok-cert.pem b/crypto/heimdal/lib/hx509/data/yutaka-pad-ok-cert.pem new file mode 100644 index 0000000..9a89e59 --- /dev/null +++ b/crypto/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/crypto/heimdal/lib/hx509/data/yutaka-pad.key b/crypto/heimdal/lib/hx509/data/yutaka-pad.key new file mode 100644 index 0000000..1763623 --- /dev/null +++ b/crypto/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/crypto/heimdal/lib/hx509/doxygen.c b/crypto/heimdal/lib/hx509/doxygen.c new file mode 100644 index 0000000..488ae4b --- /dev/null +++ b/crypto/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 enviroment functions */ diff --git a/crypto/heimdal/lib/hx509/env.c b/crypto/heimdal/lib/hx509/env.c new file mode 100644 index 0000000..f868c22 --- /dev/null +++ b/crypto/heimdal/lib/hx509/env.c @@ -0,0 +1,161 @@ +/* + * 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" +RCSID("$Id: env.c 22349 2007-12-26 19:32:49Z lha $"); + +/** + * @page page_env Hx509 enviroment functions + * + * See the library functions here: @ref hx509_env + */ + +struct hx509_env { + struct { + char *key; + char *value; + } *val; + size_t len; +}; + +/** + * Allocate a new hx509_env container object. + * + * @param context A hx509 context. + * @param env return a hx509_env structure, free with hx509_env_free(). + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_env + */ + +int +hx509_env_init(hx509_context context, hx509_env *env) +{ + *env = calloc(1, sizeof(**env)); + if (*env == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + return 0; +} + +/** + * Add a new key/value pair to the hx509_env. + * + * @param context A hx509 context. + * @param env enviroment to add the enviroment 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 + */ + +int +hx509_env_add(hx509_context context, hx509_env env, + const char *key, const char *value) +{ + void *ptr; + + ptr = realloc(env->val, sizeof(env->val[0]) * (env->len + 1)); + if (ptr == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + env->val = ptr; + env->val[env->len].key = strdup(key); + if (env->val[env->len].key == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + env->val[env->len].value = strdup(value); + if (env->val[env->len].value == NULL) { + free(env->val[env->len].key); + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + env->len++; + return 0; +} + +/** + * Search the hx509_env for a key. + * + * @param context A hx509 context. + * @param env enviroment to add the enviroment 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 + */ + +const char * +hx509_env_lfind(hx509_context context, hx509_env env, + const char *key, size_t len) +{ + size_t i; + + for (i = 0; i < env->len; i++) { + char *s = env->val[i].key; + if (strncmp(key, s, len) == 0 && s[len] == '\0') + return env->val[i].value; + } + return NULL; +} + +/** + * Free an hx509_env enviroment context. + * + * @param env the enviroment to free. + * + * @ingroup hx509_env + */ + +void +hx509_env_free(hx509_env *env) +{ + size_t i; + + for (i = 0; i < (*env)->len; i++) { + free((*env)->val[i].key); + free((*env)->val[i].value); + } + free((*env)->val); + free(*env); + *env = NULL; +} + diff --git a/crypto/heimdal/lib/hx509/error.c b/crypto/heimdal/lib/hx509/error.c new file mode 100644 index 0000000..25119ed --- /dev/null +++ b/crypto/heimdal/lib/hx509/error.c @@ -0,0 +1,223 @@ +/* + * 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" +RCSID("$Id: error.c 22332 2007-12-17 01:03:22Z lha $"); + +/** + * @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; +}; + +static void +free_error_string(hx509_error msg) +{ + while(msg) { + hx509_error m2 = msg->next; + free(msg->msg); + free(msg); + msg = m2; + } +} + +/** + * Resets the error strings the hx509 context. + * + * @param context A hx509 context. + * + * @ingroup hx509_error + */ + +void +hx509_clear_error_string(hx509_context context) +{ + free_error_string(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 + */ + +void +hx509_set_error_stringv(hx509_context context, int flags, int code, + const char *fmt, va_list ap) +{ + hx509_error msg; + + msg = calloc(1, sizeof(*msg)); + if (msg == NULL) { + hx509_clear_error_string(context); + return; + } + + if (vasprintf(&msg->msg, fmt, ap) == -1) { + hx509_clear_error_string(context); + free(msg); + return; + } + msg->code = code; + + if (flags & HX509_ERROR_APPEND) { + msg->next = context->error; + context->error = msg; + } else { + free_error_string(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 + */ + +void +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); +} + +/** + * 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 + */ + +char * +hx509_get_error_string(hx509_context context, int error_code) +{ + struct rk_strpool *p = NULL; + hx509_error msg = context->error; + + if (msg == NULL || msg->code != error_code) { + const char *cstr; + char *str; + + cstr = com_right(context->et_list, error_code); + if (cstr) + return strdup(cstr); + cstr = strerror(error_code); + if (cstr) + return strdup(cstr); + if (asprintf(&str, "<unknown error: %d>", error_code) == -1) + return NULL; + return str; + } + + for (msg = context->error; msg; msg = msg->next) + p = rk_strpoolprintf(p, "%s%s", msg->msg, + msg->next != NULL ? "; " : ""); + + return rk_strpoolcollect(p); +} + +/** + * Free error string returned by hx509_get_error_string(). + * + * @param str error string to free. + * + * @ingroup hx509_error + */ + +void +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 + */ + +void +hx509_err(hx509_context context, int exit_code, + int error_code, const char *fmt, ...) +{ + va_list ap; + const char *msg; + char *str; + + va_start(ap, fmt); + 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", str, msg); +} diff --git a/crypto/heimdal/lib/hx509/file.c b/crypto/heimdal/lib/hx509/file.c new file mode 100644 index 0000000..b076b74 --- /dev/null +++ b/crypto/heimdal/lib/hx509/file.c @@ -0,0 +1,376 @@ +/* + * 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" +RCSID("$ID$"); + +int +_hx509_map_file_os(const char *fn, heim_octet_string *os, struct stat *rsb) +{ + size_t length; + void *data; + int ret; + + ret = _hx509_map_file(fn, &data, &length, rsb); + + os->data = data; + os->length = length; + + return ret; +} + +void +_hx509_unmap_file_os(heim_octet_string *os) +{ + _hx509_unmap_file(os->data, os->length); +} + +int +_hx509_map_file(const char *fn, void **data, size_t *length, struct stat *rsb) +{ + struct stat sb; + size_t len; + ssize_t l; + int ret; + void *d; + int fd; + + *data = NULL; + *length = 0; + + fd = open(fn, O_RDONLY); + if (fd < 0) + return errno; + + if (fstat(fd, &sb) < 0) { + ret = errno; + close(fd); + return ret; + } + + len = sb.st_size; + + d = malloc(len); + if (d == NULL) { + close(fd); + return ENOMEM; + } + + l = read(fd, d, len); + close(fd); + if (l < 0 || l != len) { + free(d); + return EINVAL; + } + + if (rsb) + *rsb = sb; + *data = d; + *length = len; + return 0; +} + +void +_hx509_unmap_file(void *data, size_t len) +{ + free(data); +} + +int +_hx509_write_file(const char *fn, const void *data, size_t length) +{ + ssize_t sz; + const unsigned char *p = data; + int fd; + + fd = open(fn, O_WRONLY|O_TRUNC|O_CREAT, 0644); + if (fd < 0) + return errno; + + do { + sz = write(fd, p, length); + if (sz < 0) { + int saved_errno = errno; + close(fd); + return saved_errno; + } + if (sz == 0) + break; + length -= sz; + } while (length > 0); + + if (close(fd) == -1) + return errno; + + return 0; +} + +/* + * + */ + +static void +header(FILE *f, const char *type, const char *str) +{ + fprintf(f, "-----%s %s-----\n", type, str); +} + +int +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 + + header(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 = 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); + } + + header(f, "END", type); + + return 0; +} + +/* + * + */ + +int +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; +} + +void +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); + } +} + +/* + * + */ + +const char * +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; +} + + +/* + * + */ + +int +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; + } + /* FALLTHOUGH */ + 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 = 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; +} diff --git a/crypto/heimdal/lib/hx509/hx509-private.h b/crypto/heimdal/lib/hx509/hx509-private.h new file mode 100644 index 0000000..67bb843 --- /dev/null +++ b/crypto/heimdal/lib/hx509/hx509-private.h @@ -0,0 +1,529 @@ +/* This is a generated file */ +#ifndef __hx509_private_h__ +#define __hx509_private_h__ + +#include <stdarg.h> + +#if !defined(__GNUC__) && !defined(__attribute__) +#define __attribute__(x) +#endif + +int +_hx509_AlgorithmIdentifier_cmp ( + const AlgorithmIdentifier */*p*/, + const AlgorithmIdentifier */*q*/); + +int +_hx509_Certificate_cmp ( + const Certificate */*p*/, + const Certificate */*q*/); + +int +_hx509_Name_to_string ( + const Name */*n*/, + char **/*str*/); + +time_t +_hx509_Time2time_t (const Time */*t*/); + +void +_hx509_abort ( + const char */*fmt*/, + ...) + __attribute__ ((noreturn, format (printf, 1, 2))); + +int +_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*/); + +int +_hx509_cert_assign_key ( + hx509_cert /*cert*/, + hx509_private_key /*private_key*/); + +int +_hx509_cert_get_eku ( + hx509_context /*context*/, + hx509_cert /*cert*/, + ExtKeyUsage */*e*/); + +int +_hx509_cert_get_keyusage ( + hx509_context /*context*/, + hx509_cert /*c*/, + KeyUsage */*ku*/); + +int +_hx509_cert_get_version (const Certificate */*t*/); + +int +_hx509_cert_is_parent_cmp ( + const Certificate */*subject*/, + const Certificate */*issuer*/, + int /*allow_self_signed*/); + +int +_hx509_cert_private_decrypt ( + hx509_context /*context*/, + const heim_octet_string */*ciphertext*/, + const heim_oid */*encryption_oid*/, + hx509_cert /*p*/, + heim_octet_string */*cleartext*/); + +hx509_private_key +_hx509_cert_private_key (hx509_cert /*p*/); + +int +_hx509_cert_private_key_exportable (hx509_cert /*p*/); + +int +_hx509_cert_public_encrypt ( + hx509_context /*context*/, + const heim_octet_string */*cleartext*/, + const hx509_cert /*p*/, + heim_oid */*encryption_oid*/, + heim_octet_string */*ciphertext*/); + +void +_hx509_cert_set_release ( + hx509_cert /*cert*/, + _hx509_cert_release_func /*release*/, + void */*ctx*/); + +int +_hx509_certs_keys_add ( + hx509_context /*context*/, + hx509_certs /*certs*/, + hx509_private_key /*key*/); + +void +_hx509_certs_keys_free ( + hx509_context /*context*/, + hx509_private_key */*keys*/); + +int +_hx509_certs_keys_get ( + hx509_context /*context*/, + hx509_certs /*certs*/, + hx509_private_key **/*keys*/); + +hx509_certs +_hx509_certs_ref (hx509_certs /*certs*/); + +int +_hx509_check_key_usage ( + hx509_context /*context*/, + hx509_cert /*cert*/, + unsigned /*flags*/, + int /*req_present*/); + +int +_hx509_collector_alloc ( + hx509_context /*context*/, + hx509_lock /*lock*/, + struct hx509_collector **/*collector*/); + +int +_hx509_collector_certs_add ( + hx509_context /*context*/, + struct hx509_collector */*c*/, + hx509_cert /*cert*/); + +int +_hx509_collector_collect_certs ( + hx509_context /*context*/, + struct hx509_collector */*c*/, + hx509_certs */*ret_certs*/); + +int +_hx509_collector_collect_private_keys ( + hx509_context /*context*/, + struct hx509_collector */*c*/, + hx509_private_key **/*keys*/); + +void +_hx509_collector_free (struct hx509_collector */*c*/); + +hx509_lock +_hx509_collector_get_lock (struct hx509_collector */*c*/); + +int +_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*/); + +int +_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*/); + +int +_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*/); + +int +_hx509_find_extension_subject_key_id ( + const Certificate */*issuer*/, + SubjectKeyIdentifier */*si*/); + +int +_hx509_generate_private_key ( + hx509_context /*context*/, + struct hx509_generate_private_context */*ctx*/, + hx509_private_key */*private_key*/); + +int +_hx509_generate_private_key_bits ( + hx509_context /*context*/, + struct hx509_generate_private_context */*ctx*/, + unsigned long /*bits*/); + +void +_hx509_generate_private_key_free (struct hx509_generate_private_context **/*ctx*/); + +int +_hx509_generate_private_key_init ( + hx509_context /*context*/, + const heim_oid */*oid*/, + struct hx509_generate_private_context **/*ctx*/); + +int +_hx509_generate_private_key_is_ca ( + hx509_context /*context*/, + struct hx509_generate_private_context */*ctx*/); + +Certificate * +_hx509_get_cert (hx509_cert /*cert*/); + +void +_hx509_ks_dir_register (hx509_context /*context*/); + +void +_hx509_ks_file_register (hx509_context /*context*/); + +void +_hx509_ks_keychain_register (hx509_context /*context*/); + +void +_hx509_ks_mem_register (hx509_context /*context*/); + +void +_hx509_ks_null_register (hx509_context /*context*/); + +void +_hx509_ks_pkcs11_register (hx509_context /*context*/); + +void +_hx509_ks_pkcs12_register (hx509_context /*context*/); + +void +_hx509_ks_register ( + hx509_context /*context*/, + struct hx509_keyset_ops */*ops*/); + +int +_hx509_lock_find_cert ( + hx509_lock /*lock*/, + const hx509_query */*q*/, + hx509_cert */*c*/); + +const struct _hx509_password * +_hx509_lock_get_passwords (hx509_lock /*lock*/); + +hx509_certs +_hx509_lock_unlock_certs (hx509_lock /*lock*/); + +int +_hx509_map_file ( + const char */*fn*/, + void **/*data*/, + size_t */*length*/, + struct stat */*rsb*/); + +int +_hx509_map_file_os ( + const char */*fn*/, + heim_octet_string */*os*/, + struct stat */*rsb*/); + +int +_hx509_match_keys ( + hx509_cert /*c*/, + hx509_private_key /*private_key*/); + +int +_hx509_name_cmp ( + const Name */*n1*/, + const Name */*n2*/); + +int +_hx509_name_ds_cmp ( + const DirectoryString */*ds1*/, + const DirectoryString */*ds2*/); + +int +_hx509_name_from_Name ( + const Name */*n*/, + hx509_name */*name*/); + +int +_hx509_name_modify ( + hx509_context /*context*/, + Name */*name*/, + int /*append*/, + const heim_oid */*oid*/, + const char */*str*/); + +int +_hx509_parse_private_key ( + hx509_context /*context*/, + const heim_oid */*key_oid*/, + const void */*data*/, + size_t /*len*/, + hx509_private_key */*private_key*/); + +int +_hx509_path_append ( + hx509_context /*context*/, + hx509_path */*path*/, + hx509_cert /*cert*/); + +void +_hx509_path_free (hx509_path */*path*/); + +int +_hx509_pbe_decrypt ( + hx509_context /*context*/, + hx509_lock /*lock*/, + const AlgorithmIdentifier */*ai*/, + const heim_octet_string */*econtent*/, + heim_octet_string */*content*/); + +int +_hx509_pbe_encrypt ( + hx509_context /*context*/, + hx509_lock /*lock*/, + const AlgorithmIdentifier */*ai*/, + const heim_octet_string */*content*/, + heim_octet_string */*econtent*/); + +void +_hx509_pi_printf ( + int (*/*func*/)(void *, const char *), + void */*ctx*/, + const char */*fmt*/, + ...); + +int +_hx509_private_key2SPKI ( + hx509_context /*context*/, + hx509_private_key /*private_key*/, + SubjectPublicKeyInfo */*spki*/); + +void +_hx509_private_key_assign_rsa ( + hx509_private_key /*key*/, + void */*ptr*/); + +int +_hx509_private_key_export ( + hx509_context /*context*/, + const hx509_private_key /*key*/, + heim_octet_string */*data*/); + +int +_hx509_private_key_exportable (hx509_private_key /*key*/); + +int +_hx509_private_key_free (hx509_private_key */*key*/); + +BIGNUM * +_hx509_private_key_get_internal ( + hx509_context /*context*/, + hx509_private_key /*key*/, + const char */*type*/); + +int +_hx509_private_key_init ( + hx509_private_key */*key*/, + hx509_private_key_ops */*ops*/, + void */*keydata*/); + +int +_hx509_private_key_oid ( + hx509_context /*context*/, + const hx509_private_key /*key*/, + heim_oid */*data*/); + +int +_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*/); + +hx509_private_key +_hx509_private_key_ref (hx509_private_key /*key*/); + +const char * +_hx509_private_pem_name (hx509_private_key /*key*/); + +int +_hx509_public_encrypt ( + hx509_context /*context*/, + const heim_octet_string */*cleartext*/, + const Certificate */*cert*/, + heim_oid */*encryption_oid*/, + heim_octet_string */*ciphertext*/); + +void +_hx509_query_clear (hx509_query */*q*/); + +int +_hx509_query_match_cert ( + hx509_context /*context*/, + const hx509_query */*q*/, + hx509_cert /*cert*/); + +void +_hx509_query_statistic ( + hx509_context /*context*/, + int /*type*/, + const hx509_query */*q*/); + +int +_hx509_request_add_dns_name ( + hx509_context /*context*/, + hx509_request /*req*/, + const char */*hostname*/); + +int +_hx509_request_add_eku ( + hx509_context /*context*/, + hx509_request /*req*/, + const heim_oid */*oid*/); + +int +_hx509_request_add_email ( + hx509_context /*context*/, + hx509_request /*req*/, + const char */*email*/); + +void +_hx509_request_free (hx509_request */*req*/); + +int +_hx509_request_get_SubjectPublicKeyInfo ( + hx509_context /*context*/, + hx509_request /*req*/, + SubjectPublicKeyInfo */*key*/); + +int +_hx509_request_get_name ( + hx509_context /*context*/, + hx509_request /*req*/, + hx509_name */*name*/); + +int +_hx509_request_init ( + hx509_context /*context*/, + hx509_request */*req*/); + +int +_hx509_request_parse ( + hx509_context /*context*/, + const char */*path*/, + hx509_request */*req*/); + +int +_hx509_request_print ( + hx509_context /*context*/, + hx509_request /*req*/, + FILE */*f*/); + +int +_hx509_request_set_SubjectPublicKeyInfo ( + hx509_context /*context*/, + hx509_request /*req*/, + const SubjectPublicKeyInfo */*key*/); + +int +_hx509_request_set_name ( + hx509_context /*context*/, + hx509_request /*req*/, + hx509_name /*name*/); + +int +_hx509_request_to_pkcs10 ( + hx509_context /*context*/, + const hx509_request /*req*/, + const hx509_private_key /*signer*/, + heim_octet_string */*request*/); + +hx509_revoke_ctx +_hx509_revoke_ref (hx509_revoke_ctx /*ctx*/); + +int +_hx509_set_cert_attribute ( + hx509_context /*context*/, + hx509_cert /*cert*/, + const heim_oid */*oid*/, + const heim_octet_string */*attr*/); + +void +_hx509_unmap_file ( + void */*data*/, + size_t /*len*/); + +void +_hx509_unmap_file_os (heim_octet_string */*os*/); + +int +_hx509_unparse_Name ( + const Name */*aname*/, + char **/*str*/); + +int +_hx509_verify_signature ( + hx509_context /*context*/, + const Certificate */*signer*/, + const AlgorithmIdentifier */*alg*/, + const heim_octet_string */*data*/, + const heim_octet_string */*sig*/); + +int +_hx509_verify_signature_bitstring ( + hx509_context /*context*/, + const Certificate */*signer*/, + const AlgorithmIdentifier */*alg*/, + const heim_octet_string */*data*/, + const heim_bit_string */*sig*/); + +int +_hx509_write_file ( + const char */*fn*/, + const void */*data*/, + size_t /*length*/); + +#endif /* __hx509_private_h__ */ diff --git a/crypto/heimdal/lib/hx509/hx509-protos.h b/crypto/heimdal/lib/hx509/hx509-protos.h new file mode 100644 index 0000000..50ce1b3 --- /dev/null +++ b/crypto/heimdal/lib/hx509/hx509-protos.h @@ -0,0 +1,1049 @@ +/* This is a generated file */ +#ifndef __hx509_protos_h__ +#define __hx509_protos_h__ + +#include <stdarg.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef HX509_LIB_FUNCTION +#if defined(_WIN32) +#define HX509_LIB_FUNCTION _stdcall +#else +#define HX509_LIB_FUNCTION +#endif +#endif + +void +hx509_bitstring_print ( + const heim_bit_string */*b*/, + hx509_vprint_func /*func*/, + void */*ctx*/); + +int +hx509_ca_sign ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/, + hx509_cert /*signer*/, + hx509_cert */*certificate*/); + +int +hx509_ca_sign_self ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/, + hx509_private_key /*signer*/, + hx509_cert */*certificate*/); + +int +hx509_ca_tbs_add_crl_dp_uri ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/, + const char */*uri*/, + hx509_name /*issuername*/); + +int +hx509_ca_tbs_add_eku ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/, + const heim_oid */*oid*/); + +int +hx509_ca_tbs_add_san_hostname ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/, + const char */*dnsname*/); + +int +hx509_ca_tbs_add_san_jid ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/, + const char */*jid*/); + +int +hx509_ca_tbs_add_san_ms_upn ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/, + const char */*principal*/); + +int +hx509_ca_tbs_add_san_otherName ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/, + const heim_oid */*oid*/, + const heim_octet_string */*os*/); + +int +hx509_ca_tbs_add_san_pkinit ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/, + const char */*principal*/); + +int +hx509_ca_tbs_add_san_rfc822name ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/, + const char */*rfc822Name*/); + +void +hx509_ca_tbs_free (hx509_ca_tbs */*tbs*/); + +int +hx509_ca_tbs_init ( + hx509_context /*context*/, + hx509_ca_tbs */*tbs*/); + +int +hx509_ca_tbs_set_ca ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/, + int /*pathLenConstraint*/); + +int +hx509_ca_tbs_set_domaincontroller ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/); + +int +hx509_ca_tbs_set_notAfter ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/, + time_t /*t*/); + +int +hx509_ca_tbs_set_notAfter_lifetime ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/, + time_t /*delta*/); + +int +hx509_ca_tbs_set_notBefore ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/, + time_t /*t*/); + +int +hx509_ca_tbs_set_proxy ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/, + int /*pathLenConstraint*/); + +int +hx509_ca_tbs_set_serialnumber ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/, + const heim_integer */*serialNumber*/); + +int +hx509_ca_tbs_set_spki ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/, + const SubjectPublicKeyInfo */*spki*/); + +int +hx509_ca_tbs_set_subject ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/, + hx509_name /*subject*/); + +int +hx509_ca_tbs_set_template ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/, + int /*flags*/, + hx509_cert /*cert*/); + +int +hx509_ca_tbs_subject_expand ( + hx509_context /*context*/, + hx509_ca_tbs /*tbs*/, + hx509_env /*env*/); + +const struct units * +hx509_ca_tbs_template_units (void); + +int +hx509_cert_binary ( + hx509_context /*context*/, + hx509_cert /*c*/, + heim_octet_string */*os*/); + +int +hx509_cert_check_eku ( + hx509_context /*context*/, + hx509_cert /*cert*/, + const heim_oid */*eku*/, + int /*allow_any_eku*/); + +int +hx509_cert_cmp ( + hx509_cert /*p*/, + hx509_cert /*q*/); + +int +hx509_cert_find_subjectAltName_otherName ( + hx509_context /*context*/, + hx509_cert /*cert*/, + const heim_oid */*oid*/, + hx509_octet_string_list */*list*/); + +void +hx509_cert_free (hx509_cert /*cert*/); + +int +hx509_cert_get_SPKI ( + hx509_context /*context*/, + hx509_cert /*p*/, + SubjectPublicKeyInfo */*spki*/); + +int +hx509_cert_get_SPKI_AlgorithmIdentifier ( + hx509_context /*context*/, + hx509_cert /*p*/, + AlgorithmIdentifier */*alg*/); + +hx509_cert_attribute +hx509_cert_get_attribute ( + hx509_cert /*cert*/, + const heim_oid */*oid*/); + +int +hx509_cert_get_base_subject ( + hx509_context /*context*/, + hx509_cert /*c*/, + hx509_name */*name*/); + +const char * +hx509_cert_get_friendly_name (hx509_cert /*cert*/); + +int +hx509_cert_get_issuer ( + hx509_cert /*p*/, + hx509_name */*name*/); + +time_t +hx509_cert_get_notAfter (hx509_cert /*p*/); + +time_t +hx509_cert_get_notBefore (hx509_cert /*p*/); + +int +hx509_cert_get_serialnumber ( + hx509_cert /*p*/, + heim_integer */*i*/); + +int +hx509_cert_get_subject ( + hx509_cert /*p*/, + hx509_name */*name*/); + +int +hx509_cert_have_private_key (hx509_cert /*p*/); + +int +hx509_cert_init ( + hx509_context /*context*/, + const Certificate */*c*/, + hx509_cert */*cert*/); + +int +hx509_cert_init_data ( + hx509_context /*context*/, + const void */*ptr*/, + size_t /*len*/, + hx509_cert */*cert*/); + +int +hx509_cert_keyusage_print ( + hx509_context /*context*/, + hx509_cert /*c*/, + char **/*s*/); + +hx509_cert +hx509_cert_ref (hx509_cert /*cert*/); + +int +hx509_cert_set_friendly_name ( + hx509_cert /*cert*/, + const char */*name*/); + +int +hx509_certs_add ( + hx509_context /*context*/, + hx509_certs /*certs*/, + hx509_cert /*cert*/); + +int +hx509_certs_append ( + hx509_context /*context*/, + hx509_certs /*to*/, + hx509_lock /*lock*/, + const char */*name*/); + +int +hx509_certs_end_seq ( + hx509_context /*context*/, + hx509_certs /*certs*/, + hx509_cursor /*cursor*/); + +int +hx509_certs_find ( + hx509_context /*context*/, + hx509_certs /*certs*/, + const hx509_query */*q*/, + hx509_cert */*r*/); + +void +hx509_certs_free (hx509_certs */*certs*/); + +int +hx509_certs_info ( + hx509_context /*context*/, + hx509_certs /*certs*/, + int (*/*func*/)(void *, const char *), + void */*ctx*/); + +int +hx509_certs_init ( + hx509_context /*context*/, + const char */*name*/, + int /*flags*/, + hx509_lock /*lock*/, + hx509_certs */*certs*/); + +int +hx509_certs_iter ( + hx509_context /*context*/, + hx509_certs /*certs*/, + int (*/*func*/)(hx509_context, void *, hx509_cert), + void */*ctx*/); + +int +hx509_certs_merge ( + hx509_context /*context*/, + hx509_certs /*to*/, + hx509_certs /*from*/); + +int +hx509_certs_next_cert ( + hx509_context /*context*/, + hx509_certs /*certs*/, + hx509_cursor /*cursor*/, + hx509_cert */*cert*/); + +int +hx509_certs_start_seq ( + hx509_context /*context*/, + hx509_certs /*certs*/, + hx509_cursor */*cursor*/); + +int +hx509_certs_store ( + hx509_context /*context*/, + hx509_certs /*certs*/, + int /*flags*/, + hx509_lock /*lock*/); + +int +hx509_ci_print_names ( + hx509_context /*context*/, + void */*ctx*/, + hx509_cert /*c*/); + +void +hx509_clear_error_string (hx509_context /*context*/); + +int +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*/); + +int +hx509_cms_decrypt_encrypted ( + hx509_context /*context*/, + hx509_lock /*lock*/, + const void */*data*/, + size_t /*length*/, + heim_oid */*contentType*/, + heim_octet_string */*content*/); + +int +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*/); + +int +hx509_cms_unenvelope ( + hx509_context /*context*/, + hx509_certs /*certs*/, + int /*flags*/, + const void */*data*/, + size_t /*length*/, + const heim_octet_string */*encryptedContent*/, + heim_oid */*contentType*/, + heim_octet_string */*content*/); + +int +hx509_cms_unwrap_ContentInfo ( + const heim_octet_string */*in*/, + heim_oid */*oid*/, + heim_octet_string */*out*/, + int */*have_data*/); + +int +hx509_cms_verify_signed ( + hx509_context /*context*/, + hx509_verify_ctx /*ctx*/, + 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*/); + +int +hx509_cms_wrap_ContentInfo ( + const heim_oid */*oid*/, + const heim_octet_string */*buf*/, + heim_octet_string */*res*/); + +void +hx509_context_free (hx509_context */*context*/); + +int +hx509_context_init (hx509_context */*context*/); + +void +hx509_context_set_missing_revoke ( + hx509_context /*context*/, + int /*flag*/); + +int +hx509_crl_add_revoked_certs ( + hx509_context /*context*/, + hx509_crl /*crl*/, + hx509_certs /*certs*/); + +int +hx509_crl_alloc ( + hx509_context /*context*/, + hx509_crl */*crl*/); + +void +hx509_crl_free ( + hx509_context /*context*/, + hx509_crl */*crl*/); + +int +hx509_crl_lifetime ( + hx509_context /*context*/, + hx509_crl /*crl*/, + int /*delta*/); + +int +hx509_crl_sign ( + hx509_context /*context*/, + hx509_cert /*signer*/, + hx509_crl /*crl*/, + heim_octet_string */*os*/); + +const AlgorithmIdentifier * +hx509_crypto_aes128_cbc (void); + +const AlgorithmIdentifier * +hx509_crypto_aes256_cbc (void); + +int +hx509_crypto_available ( + hx509_context /*context*/, + int /*type*/, + hx509_cert /*source*/, + AlgorithmIdentifier **/*val*/, + unsigned int */*plen*/); + +int +hx509_crypto_decrypt ( + hx509_crypto /*crypto*/, + const void */*data*/, + const size_t /*length*/, + heim_octet_string */*ivec*/, + heim_octet_string */*clear*/); + +const AlgorithmIdentifier * +hx509_crypto_des_rsdi_ede3_cbc (void); + +void +hx509_crypto_destroy (hx509_crypto /*crypto*/); + +int +hx509_crypto_encrypt ( + hx509_crypto /*crypto*/, + const void */*data*/, + const size_t /*length*/, + const heim_octet_string */*ivec*/, + heim_octet_string **/*ciphertext*/); + +const heim_oid * +hx509_crypto_enctype_by_name (const char */*name*/); + +void +hx509_crypto_free_algs ( + AlgorithmIdentifier */*val*/, + unsigned int /*len*/); + +int +hx509_crypto_get_params ( + hx509_context /*context*/, + hx509_crypto /*crypto*/, + const heim_octet_string */*ivec*/, + heim_octet_string */*param*/); + +int +hx509_crypto_init ( + hx509_context /*context*/, + const char */*provider*/, + const heim_oid */*enctype*/, + hx509_crypto */*crypto*/); + +const char * +hx509_crypto_provider (hx509_crypto /*crypto*/); + +int +hx509_crypto_random_iv ( + hx509_crypto /*crypto*/, + heim_octet_string */*ivec*/); + +int +hx509_crypto_select ( + const hx509_context /*context*/, + int /*type*/, + const hx509_private_key /*source*/, + hx509_peer_info /*peer*/, + AlgorithmIdentifier */*selected*/); + +int +hx509_crypto_set_key_data ( + hx509_crypto /*crypto*/, + const void */*data*/, + size_t /*length*/); + +int +hx509_crypto_set_key_name ( + hx509_crypto /*crypto*/, + const char */*name*/); + +int +hx509_crypto_set_params ( + hx509_context /*context*/, + hx509_crypto /*crypto*/, + const heim_octet_string */*param*/, + heim_octet_string */*ivec*/); + +int +hx509_crypto_set_random_key ( + hx509_crypto /*crypto*/, + heim_octet_string */*key*/); + +int +hx509_env_add ( + hx509_context /*context*/, + hx509_env /*env*/, + const char */*key*/, + const char */*value*/); + +void +hx509_env_free (hx509_env */*env*/); + +int +hx509_env_init ( + hx509_context /*context*/, + hx509_env */*env*/); + +const char * +hx509_env_lfind ( + hx509_context /*context*/, + hx509_env /*env*/, + const char */*key*/, + size_t /*len*/); + +void +hx509_err ( + hx509_context /*context*/, + int /*exit_code*/, + int /*error_code*/, + const char */*fmt*/, + ...); + +void +hx509_free_error_string (char */*str*/); + +void +hx509_free_octet_string_list (hx509_octet_string_list */*list*/); + +int +hx509_general_name_unparse ( + GeneralName */*name*/, + char **/*str*/); + +char * +hx509_get_error_string ( + hx509_context /*context*/, + int /*error_code*/); + +int +hx509_get_one_cert ( + hx509_context /*context*/, + hx509_certs /*certs*/, + hx509_cert */*c*/); + +int +hx509_lock_add_cert ( + hx509_context /*context*/, + hx509_lock /*lock*/, + hx509_cert /*cert*/); + +int +hx509_lock_add_certs ( + hx509_context /*context*/, + hx509_lock /*lock*/, + hx509_certs /*certs*/); + +int +hx509_lock_add_password ( + hx509_lock /*lock*/, + const char */*password*/); + +int +hx509_lock_command_string ( + hx509_lock /*lock*/, + const char */*string*/); + +void +hx509_lock_free (hx509_lock /*lock*/); + +int +hx509_lock_init ( + hx509_context /*context*/, + hx509_lock */*lock*/); + +int +hx509_lock_prompt ( + hx509_lock /*lock*/, + hx509_prompt */*prompt*/); + +void +hx509_lock_reset_certs ( + hx509_context /*context*/, + hx509_lock /*lock*/); + +void +hx509_lock_reset_passwords (hx509_lock /*lock*/); + +void +hx509_lock_reset_promper (hx509_lock /*lock*/); + +int +hx509_lock_set_prompter ( + hx509_lock /*lock*/, + hx509_prompter_fct /*prompt*/, + void */*data*/); + +int +hx509_name_binary ( + const hx509_name /*name*/, + heim_octet_string */*os*/); + +int +hx509_name_cmp ( + hx509_name /*n1*/, + hx509_name /*n2*/); + +int +hx509_name_copy ( + hx509_context /*context*/, + const hx509_name /*from*/, + hx509_name */*to*/); + +int +hx509_name_expand ( + hx509_context /*context*/, + hx509_name /*name*/, + hx509_env /*env*/); + +void +hx509_name_free (hx509_name */*name*/); + +int +hx509_name_is_null_p (const hx509_name /*name*/); + +int +hx509_name_normalize ( + hx509_context /*context*/, + hx509_name /*name*/); + +int +hx509_name_to_Name ( + const hx509_name /*from*/, + Name */*to*/); + +int +hx509_name_to_string ( + const hx509_name /*name*/, + char **/*str*/); + +int +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*/); + +int +hx509_ocsp_verify ( + hx509_context /*context*/, + time_t /*now*/, + hx509_cert /*cert*/, + int /*flags*/, + const void */*data*/, + size_t /*length*/, + time_t */*expiration*/); + +void +hx509_oid_print ( + const heim_oid */*oid*/, + hx509_vprint_func /*func*/, + void */*ctx*/); + +int +hx509_oid_sprint ( + const heim_oid */*oid*/, + char **/*str*/); + +int +hx509_parse_name ( + hx509_context /*context*/, + const char */*str*/, + hx509_name */*name*/); + +int +hx509_peer_info_alloc ( + hx509_context /*context*/, + hx509_peer_info */*peer*/); + +void +hx509_peer_info_free (hx509_peer_info /*peer*/); + +int +hx509_peer_info_set_cert ( + hx509_peer_info /*peer*/, + hx509_cert /*cert*/); + +int +hx509_peer_info_set_cms_algs ( + hx509_context /*context*/, + hx509_peer_info /*peer*/, + const AlgorithmIdentifier */*val*/, + size_t /*len*/); + +int +hx509_pem_add_header ( + hx509_pem_header **/*headers*/, + const char */*header*/, + const char */*value*/); + +const char * +hx509_pem_find_header ( + const hx509_pem_header */*h*/, + const char */*header*/); + +void +hx509_pem_free_header (hx509_pem_header */*headers*/); + +int +hx509_pem_read ( + hx509_context /*context*/, + FILE */*f*/, + hx509_pem_read_func /*func*/, + void */*ctx*/); + +int +hx509_pem_write ( + hx509_context /*context*/, + const char */*type*/, + hx509_pem_header */*headers*/, + FILE */*f*/, + const void */*data*/, + size_t /*size*/); + +void +hx509_print_stdout ( + void */*ctx*/, + const char */*fmt*/, + va_list /*va*/); + +int +hx509_prompt_hidden (hx509_prompt_type /*type*/); + +int +hx509_query_alloc ( + hx509_context /*context*/, + hx509_query **/*q*/); + +void +hx509_query_free ( + hx509_context /*context*/, + hx509_query */*q*/); + +int +hx509_query_match_cmp_func ( + hx509_query */*q*/, + int (*/*func*/)(void *, hx509_cert), + void */*ctx*/); + +int +hx509_query_match_friendly_name ( + hx509_query */*q*/, + const char */*name*/); + +int +hx509_query_match_issuer_serial ( + hx509_query */*q*/, + const Name */*issuer*/, + const heim_integer */*serialNumber*/); + +void +hx509_query_match_option ( + hx509_query */*q*/, + hx509_query_option /*option*/); + +void +hx509_query_statistic_file ( + hx509_context /*context*/, + const char */*fn*/); + +void +hx509_query_unparse_stats ( + hx509_context /*context*/, + int /*printtype*/, + FILE */*out*/); + +int +hx509_revoke_add_crl ( + hx509_context /*context*/, + hx509_revoke_ctx /*ctx*/, + const char */*path*/); + +int +hx509_revoke_add_ocsp ( + hx509_context /*context*/, + hx509_revoke_ctx /*ctx*/, + const char */*path*/); + +void +hx509_revoke_free (hx509_revoke_ctx */*ctx*/); + +int +hx509_revoke_init ( + hx509_context /*context*/, + hx509_revoke_ctx */*ctx*/); + +int +hx509_revoke_ocsp_print ( + hx509_context /*context*/, + const char */*path*/, + FILE */*out*/); + +int +hx509_revoke_verify ( + hx509_context /*context*/, + hx509_revoke_ctx /*ctx*/, + hx509_certs /*certs*/, + time_t /*now*/, + hx509_cert /*cert*/, + hx509_cert /*parent_cert*/); + +void +hx509_set_error_string ( + hx509_context /*context*/, + int /*flags*/, + int /*code*/, + const char */*fmt*/, + ...); + +void +hx509_set_error_stringv ( + hx509_context /*context*/, + int /*flags*/, + int /*code*/, + const char */*fmt*/, + va_list /*ap*/); + +const AlgorithmIdentifier * +hx509_signature_md2 (void); + +const AlgorithmIdentifier * +hx509_signature_md5 (void); + +const AlgorithmIdentifier * +hx509_signature_rsa (void); + +const AlgorithmIdentifier * +hx509_signature_rsa_pkcs1_x509 (void); + +const AlgorithmIdentifier * +hx509_signature_rsa_with_md2 (void); + +const AlgorithmIdentifier * +hx509_signature_rsa_with_md5 (void); + +const AlgorithmIdentifier * +hx509_signature_rsa_with_sha1 (void); + +const AlgorithmIdentifier * +hx509_signature_rsa_with_sha256 (void); + +const AlgorithmIdentifier * +hx509_signature_rsa_with_sha384 (void); + +const AlgorithmIdentifier * +hx509_signature_rsa_with_sha512 (void); + +const AlgorithmIdentifier * +hx509_signature_sha1 (void); + +const AlgorithmIdentifier * +hx509_signature_sha256 (void); + +const AlgorithmIdentifier * +hx509_signature_sha384 (void); + +const AlgorithmIdentifier * +hx509_signature_sha512 (void); + +int +hx509_unparse_der_name ( + const void */*data*/, + size_t /*length*/, + char **/*str*/); + +int +hx509_validate_cert ( + hx509_context /*context*/, + hx509_validate_ctx /*ctx*/, + hx509_cert /*cert*/); + +void +hx509_validate_ctx_add_flags ( + hx509_validate_ctx /*ctx*/, + int /*flags*/); + +void +hx509_validate_ctx_free (hx509_validate_ctx /*ctx*/); + +int +hx509_validate_ctx_init ( + hx509_context /*context*/, + hx509_validate_ctx */*ctx*/); + +void +hx509_validate_ctx_set_print ( + hx509_validate_ctx /*ctx*/, + hx509_vprint_func /*func*/, + void */*c*/); + +void +hx509_verify_attach_anchors ( + hx509_verify_ctx /*ctx*/, + hx509_certs /*set*/); + +void +hx509_verify_attach_revoke ( + hx509_verify_ctx /*ctx*/, + hx509_revoke_ctx /*revoke_ctx*/); + +void +hx509_verify_ctx_f_allow_default_trustanchors ( + hx509_verify_ctx /*ctx*/, + int /*boolean*/); + +void +hx509_verify_destroy_ctx (hx509_verify_ctx /*ctx*/); + +int +hx509_verify_hostname ( + hx509_context /*context*/, + const hx509_cert /*cert*/, + int /*flags*/, + hx509_hostname_type /*type*/, + const char */*hostname*/, + const struct sockaddr */*sa*/, + int /*sa_size*/); + +int +hx509_verify_init_ctx ( + hx509_context /*context*/, + hx509_verify_ctx */*ctx*/); + +int +hx509_verify_path ( + hx509_context /*context*/, + hx509_verify_ctx /*ctx*/, + hx509_cert /*cert*/, + hx509_certs /*pool*/); + +void +hx509_verify_set_max_depth ( + hx509_verify_ctx /*ctx*/, + unsigned int /*max_depth*/); + +void +hx509_verify_set_proxy_certificate ( + hx509_verify_ctx /*ctx*/, + int /*boolean*/); + +void +hx509_verify_set_strict_rfc3280_verification ( + hx509_verify_ctx /*ctx*/, + int /*boolean*/); + +void +hx509_verify_set_time ( + hx509_verify_ctx /*ctx*/, + time_t /*t*/); + +int +hx509_verify_signature ( + hx509_context /*context*/, + const hx509_cert /*signer*/, + const AlgorithmIdentifier */*alg*/, + const heim_octet_string */*data*/, + const heim_octet_string */*sig*/); + +void +hx509_xfree (void */*ptr*/); + +#ifdef __cplusplus +} +#endif + +#endif /* __hx509_protos_h__ */ diff --git a/crypto/heimdal/lib/hx509/hx509.h b/crypto/heimdal/lib/hx509/hx509.h new file mode 100644 index 0000000..be02f63 --- /dev/null +++ b/crypto/heimdal/lib/hx509/hx509.h @@ -0,0 +1,148 @@ +/* + * 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: hx509.h 22464 2008-01-16 14:24:50Z lha $ */ + +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_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 *hx509_env; +typedef struct hx509_crl *hx509_crl; + +typedef void (*hx509_vprint_func)(void *, const char *, va_list); + +enum { + HX509_VHN_F_ALLOW_NO_MATCH = 1 +}; + +enum { + HX509_VALIDATE_F_VALIDATE = 1, + HX509_VALIDATE_F_VERBOSE = 2 +}; + +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 + +/* 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 + +/* 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 + +/* flags hx509_cms_create_signed* */ +#define HX509_CMS_SIGATURE_DETACHED 1 +#define HX509_CMS_SIGATURE_ID_NAME 2 + +/* hx509_verify_hostname nametype */ +typedef enum { + HX509_HN_HOSTNAME = 0, + HX509_HN_DNSSRV +} hx509_hostname_type; + +#include <hx509-protos.h> diff --git a/crypto/heimdal/lib/hx509/hx509_err.et b/crypto/heimdal/lib/hx509/hx509_err.et new file mode 100644 index 0000000..8fc5cb8 --- /dev/null +++ b/crypto/heimdal/lib/hx509/hx509_err.et @@ -0,0 +1,101 @@ +# +# Error messages for the hx509 library +# +# This might look like a com_err file, but is not +# +id "$Id: hx509_err.et 22329 2007-12-15 05:13:14Z lha $" + +error_table hx +prefix HX509 + +# path validateion 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 verifing constraints" +error_code RANGE, "Number too large" +error_code NAME_CONSTRAINT_ERROR, "Error while verifing 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 malformated" +error_code CERTIFICATE_MALFORMED, "Certificate is malformated" +error_code CERTIFICATE_MISSING_EKU, "Certificate is missing a required EKU" +error_code PROXY_CERTIFICATE_NOT_CANONICALIZED, "Proxy certificate not canonicalize" + +# 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 bewteen oids" +error_code NO_PROMPTER, "No prompter function defined" +error_code SIGNATURE_WITHOUT_SIGNER, "Signature require signer, but non available" +error_code RSA_PUBLIC_ENCRYPT, "RSA public encyption failed" +error_code RSA_PRIVATE_ENCRYPT, "RSA public encyption failed" +error_code RSA_PUBLIC_DECRYPT, "RSA private decryption failed" +error_code RSA_PRIVATE_DECRYPT, "RSA private decryption failed" + +# 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" + +end diff --git a/crypto/heimdal/lib/hx509/hx_locl.h b/crypto/heimdal/lib/hx509/hx_locl.h new file mode 100644 index 0000000..145bfcc --- /dev/null +++ b/crypto/heimdal/lib/hx509/hx_locl.h @@ -0,0 +1,199 @@ +/* + * 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: hx_locl.h 21083 2007-06-13 02:11:19Z lha $ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <errno.h> +#include <strings.h> +#include <assert.h> +#include <stdarg.h> +#include <err.h> +#include <getarg.h> +#include <base64.h> +#include <hex.h> +#include <roken.h> +#include <com_err.h> +#include <parse_units.h> +#include <parse_bytes.h> + +#include <krb5-types.h> + +#include <rfc2459_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> + +#include "crypto-headers.h" + +struct hx509_keyset_ops; +struct hx509_collector; +struct hx509_generate_private_context; +typedef struct hx509_path hx509_path; + +#include <hx509.h> + +typedef void (*_hx509_cert_release_func)(struct hx509_cert_data *, void *); + +typedef struct hx509_private_key_ops hx509_private_key_ops; + +#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_MASK 0x3fffff + 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)(void *, hx509_cert); + void *cmp_func_ctx; + heim_octet_string *keyhash_sha1; + time_t timenow; +}; + +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); +}; + +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) + hx509_error error; + struct et_list *et_list; + char *querystat; + hx509_certs default_trust_anchors; +}; + +/* _hx509_calculate_path flag field */ +#define HX509_CALCULATE_PATH_NO_ANCHOR 1 + +extern const AlgorithmIdentifier * _hx509_crypto_default_sig_alg; +extern const AlgorithmIdentifier * _hx509_crypto_default_digest_alg; +extern const AlgorithmIdentifier * _hx509_crypto_default_secret_alg; + +/* + * Configurable options + */ + +#ifdef __APPLE__ +#define HX509_DEFAULT_ANCHORS "KEYCHAIN:system-anchors" +#endif diff --git a/crypto/heimdal/lib/hx509/hxtool-commands.in b/crypto/heimdal/lib/hx509/hxtool-commands.in new file mode 100644 index 0000000..b648ecf --- /dev/null +++ b/crypto/heimdal/lib/hx509/hxtool-commands.in @@ -0,0 +1,707 @@ +/* + * 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: hxtool-commands.in 21343 2007-06-26 14:21:55Z lha $ */ + +command = { + name = "cms-create-sd" + 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 = "id-by-name" + type = "flag" + help = "use subject name for CMS Identifier" + } + min_args="2" + max_args="2" + argument="in-file out-file" + help = "Wrap a file within a SignedData object" +} +command = { + name = "cms-verify-sd" + option = { + long = "anchors" + 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 = "signed-content" + type = "string" + help = "file containing content" + } + min_args="2" + 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" + } + 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" + } + 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 = "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 = "request-create" + option = { + long = "subject" + type = "string" + help = "Subject DN" + } + option = { + long = "email" + type = "strings" + help = "Email address in SubjectAltName" + } + option = { + long = "dnsname" + type = "strings" + help = "Hostname or domainname in 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 = "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" + } + 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" + } + 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 = "Type of certificate to issue" + } + option = { + long = "lifetime" + type = "string" + help = "Lifetime of certificate" + } + 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 = "hostname" + type = "strings" + help = "DNS 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 = "string" + 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 = "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 = { + name = "help" + name = "?" + argument = "[command]" + min_args = "0" + max_args = "1" + help = "Help! I need somebody" +} diff --git a/crypto/heimdal/lib/hx509/hxtool.c b/crypto/heimdal/lib/hx509/hxtool.c new file mode 100644 index 0000000..55410b1 --- /dev/null +++ b/crypto/heimdal/lib/hx509/hxtool.c @@ -0,0 +1,1986 @@ +/* + * 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" +RCSID("$Id: hxtool.c 22333 2007-12-17 01:03:43Z lha $"); + +#include <hxtool-commands.h> +#include <sl.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 }, + { "version", 0, arg_flag, &version_flag }, + { "help", 0, arg_flag, &help_flag } +}; +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 void +certs_strings(hx509_context context, const char *type, hx509_certs certs, + hx509_lock lock, const getarg_strings *s) +{ + int i, ret; + + for (i = 0; i < s->num_strings; i++) { + ret = hx509_certs_append(context, certs, lock, s->strings[i]); + if (ret) + hx509_err(context, 1, ret, + "hx509_certs_append: %s %s", type, s->strings[i]); + } +} + +/* + * + */ + +static void +parse_oid(const char *str, const heim_oid *def, heim_oid *oid) +{ + int ret; + if (str) + 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 context, + hx509_peer_info *peer, + const getarg_strings *s) +{ + AlgorithmIdentifier *val; + int ret, i; + + ret = hx509_peer_info_alloc(context, peer); + if (ret) + hx509_err(context, 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(context, *peer, val, s->num_strings); + if (ret) + hx509_err(context, 1, ret, "hx509_peer_info_set_cms_algs"); + + for (i = 0; i < s->num_strings; i++) + free_AlgorithmIdentifier(&val[i]); + free(val); +} + +/* + * + */ + +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; + + size_t sz; + void *p; + + 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_map_file(argv[0], &p, &sz, NULL); + if (ret) + err(1, "map_file: %s: %d", argv[0], ret); + + if (opt->signed_content_string) { + ret = _hx509_map_file_os(opt->signed_content_string, &signeddata, NULL); + if (ret) + err(1, "map_file: %s: %d", opt->signed_content_string, ret); + sd = &signeddata; + } + + ret = hx509_verify_init_ctx(context, &ctx); + + ret = hx509_certs_init(context, "MEMORY:cms-anchors", 0, NULL, &anchors); + ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &store); + + certs_strings(context, "anchors", anchors, lock, &opt->anchors_strings); + certs_strings(context, "store", store, lock, &opt->certificate_strings); + + 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, oid_id_pkcs7_signedData()) != 0) + errx(1, "Content is not SignedData"); + der_free_oid(&oid); + + co = uwco; + } + + hx509_verify_attach_anchors(ctx, anchors); + + ret = hx509_cms_verify_signed(context, ctx, co.data, co.length, sd, + store, &type, &c, &signers); + if (co.data != p) + der_free_octet_string(&co); + if (ret) + hx509_err(context, 1, ret, "hx509_cms_verify_signed"); + + { + char *str; + der_print_heim_oid(&type, '.', &str); + printf("type: %s\n", str); + free(str); + der_free_oid(&type); + } + printf("signers:\n"); + hx509_certs_iter(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); + + ret = _hx509_write_file(argv[1], c.data, c.length); + if (ret) + errx(1, "hx509_write_file: %d", ret); + + der_free_octet_string(&c); + _hx509_unmap_file(p, sz); + if (sd) + _hx509_unmap_file_os(sd); + + 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; + hx509_cert cert; + size_t sz; + void *p; + int ret, flags = 0; + char *signer_name = NULL; + + memset(&contentType, 0, sizeof(contentType)); + + if (argc < 2) + errx(1, "argc < 2"); + + hx509_lock_init(context, &lock); + lock_strings(lock, &opt->pass_strings); + + ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &store); + ret = hx509_certs_init(context, "MEMORY:cert-pool", 0, NULL, &pool); + + 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); + certs_strings(context, "anchors", anchors, lock, &opt->anchors_strings); + } else + anchors = NULL; + + if (opt->detached_signature_flag) + flags |= HX509_CMS_SIGATURE_DETACHED; + if (opt->id_by_name_flag) + flags |= HX509_CMS_SIGATURE_ID_NAME; + + 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_find(context, store, q, &cert); + hx509_query_free(context, q); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_find"); + + ret = _hx509_map_file(argv[0], &p, &sz, NULL); + if (ret) + err(1, "map_file: %s: %d", argv[0], ret); + + if (opt->peer_alg_strings.num_strings) + peer_strings(context, &peer, &opt->peer_alg_strings); + + parse_oid(opt->content_type_string, oid_id_pkcs7_data(), &contentType); + + ret = hx509_cms_create_signed_1(context, + flags, + &contentType, + p, + sz, + NULL, + cert, + peer, + anchors, + pool, + &o); + if (ret) + errx(1, "hx509_cms_create_signed: %d", ret); + + { + hx509_name name; + + 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_certs_free(&anchors); + hx509_certs_free(&pool); + hx509_cert_free(cert); + hx509_certs_free(&store); + _hx509_unmap_file(p, sz); + 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(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"); + hx509_pem_add_header(&header, "Signer", signer_name); + + f = fopen(argv[1], "w"); + if (f == NULL) + err(1, "open %s", argv[1]); + + 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(argv[1], o.data, o.length); + if (ret) + errx(1, "hx509_write_file: %d", ret); + } + + free(signer_name); + free(o.data); + + 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; + + hx509_lock_init(context, &lock); + lock_strings(lock, &opt->pass_strings); + + ret = _hx509_map_file(argv[0], &p, &sz, NULL); + 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, 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); + + ret = hx509_cms_unenvelope(context, certs, 0, co.data, co.length, + NULL, &contentType, &o); + if (co.data != p) + der_free_octet_string(&co); + if (ret) + hx509_err(context, 1, ret, "hx509_cms_unenvelope"); + + _hx509_unmap_file(p, sz); + 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; + + memset(&contentType, 0, sizeof(contentType)); + + hx509_lock_init(context, &lock); + lock_strings(lock, &opt->pass_strings); + + ret = _hx509_map_file(argv[0], &p, &sz, NULL); + if (ret) + err(1, "map_file: %s: %d", argv[0], ret); + + ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs); + + certs_strings(context, "store", certs, lock, &opt->certificate_strings); + + 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, oid_id_pkcs7_data(), &contentType); + + ret = hx509_cms_envelope_1(context, 0, cert, p, sz, enctype, + &contentType, &o); + if (ret) + errx(1, "hx509_cms_envelope_1: %d", ret); + + hx509_cert_free(cert); + hx509_certs_free(&certs); + _hx509_unmap_file(p, sz); + der_free_oid(&contentType); + + if (opt->content_info_flag) { + heim_octet_string wo; + + ret = hx509_cms_wrap_ContentInfo(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) +{ + hx509_name name; + const char *fn; + char *str; + 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_cert_get_issuer(cert, &name); + hx509_name_to_string(name, &str); + hx509_name_free(&name); + printf(" issuer: \"%s\"\n", str); + free(str); + + ret = hx509_cert_get_subject(cert, &name); + hx509_name_to_string(name, &str); + hx509_name_free(&name); + printf(" subject: \"%s\"\n", str); + free(str); + + { + heim_integer serialNumber; + + hx509_cert_get_serialnumber(cert, &serialNumber); + der_print_hex_heim_integer(&serialNumber, &str); + der_free_heim_integer(&serialNumber); + printf(" serial: %s\n", str); + free(str); + } + + printf(" keyusage: "); + ret = hx509_cert_keyusage_print(hxcontext, cert, &str); + if (ret == 0) { + printf("%s\n", str); + free(str); + } else + printf("no"); + + 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 +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; +} + +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--) { + int ret; + ret = hx509_certs_init(context, argv[0], 0, lock, &certs); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_init"); + if (opt->info_flag) + hx509_certs_info(context, certs, NULL, NULL); + hx509_certs_iter(context, certs, print_f, &s); + hx509_certs_free(&certs); + argv++; + } + + hx509_lock_free(lock); + + return 0; +} + + +static int +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--) { + int ret; + ret = hx509_certs_init(context, argv[0], 0, lock, &certs); + if (ret) + errx(1, "hx509_certs_init: %d", ret); + hx509_certs_iter(context, certs, validate_f, ctx); + hx509_certs_free(&certs); + argv++; + } + 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 lock; + int ret; + + hx509_lock_init(context, &lock); + lock_strings(lock, &opt->in_pass_strings); + + ret = hx509_certs_init(context, argv[argc - 1], + HX509_CERTS_CREATE, lock, &certs); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_init"); + + while(argc-- > 1) { + int ret; + ret = hx509_certs_append(context, certs, lock, argv[0]); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_append"); + argv++; + } + + ret = hx509_certs_store(context, certs, 0, NULL); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_store"); + + hx509_certs_free(&certs); + hx509_lock_free(lock); + + return 0; +} + +struct verify { + hx509_verify_ctx ctx; + hx509_certs chain; + const char *hostname; + int errors; +}; + +static int +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 + 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); + ret = hx509_certs_init(context, "MEMORY:anchors", 0, NULL, &anchors); + ret = hx509_certs_init(context, "MEMORY:chain", 0, NULL, &chain); + ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &certs); + + 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--) { + char *s = *argv++; + + if (strncmp(s, "chain:", 6) == 0) { + s += 6; + + ret = hx509_certs_append(context, chain, NULL, s); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_append: chain: %s: %d", s, ret); + + } else if (strncmp(s, "anchor:", 7) == 0) { + s += 7; + + ret = hx509_certs_append(context, anchors, NULL, s); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_append: anchor: %s: %d", s, ret); + + } else if (strncmp(s, "cert:", 5) == 0) { + s += 5; + + ret = hx509_certs_append(context, certs, NULL, s); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_append: certs: %s: %d", + s, 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:", 4) == 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); + } + } + + hx509_verify_attach_anchors(ctx, anchors); + hx509_verify_attach_revoke(ctx, revoke_ctx); + + v.ctx = ctx; + v.chain = chain; + + hx509_certs_iter(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.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); + + while (argc > 0) { + + ret = hx509_certs_append(context, certs, lock, argv[0]); + if (ret) + errx(1, "hx509_certs_append: %s: %d", argv[0], ret); + + argc--; + argv++; + } + + if (opt->friendlyname_string) + hx509_query_match_friendly_name(q, opt->friendlyname_string); + + 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); + + 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); + + certs_strings(context, "ocsp-pool", pool, lock, &opt->pool_strings); + + file = argv[0]; + + ret = hx509_certs_init(context, "MEMORY:ocsp-req", 0, NULL, &reqcerts); + + for (i = 1; i < argc; i++) { + ret = hx509_certs_append(context, reqcerts, lock, argv[i]); + if (ret) + errx(1, "hx509_certs_append: req: %s: %d", argv[i], ret); + } + + 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; +} + +/* + * + */ + +static int +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(opt->ocsp_file_string, &os.data, &os.length, NULL); + if (ret) + err(1, "map_file: %s: %d", argv[0], ret); + + ret = hx509_certs_init(context, "MEMORY:test-certs", 0, NULL, &certs); + + for (i = 0; i < argc; i++) { + ret = hx509_certs_append(context, certs, lock, argv[i]); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_append: %s", argv[i]); + } + + ret = hx509_certs_iter(context, certs, verify_o, &os); + + hx509_certs_free(&certs); + _hx509_unmap_file(os.data, os.length); + 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; + int ret; + + *key = NULL; + + ret = hx509_certs_init(context, fn, 0, NULL, &certs); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_init: %s", fn); + + 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", fn); + + *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; + + if (type) { + BIGNUM *e; + RSA *rsa; + unsigned char *p0, *p; + size_t len; + int bits = 1024; + + if (fn == NULL) + errx(1, "no key argument, don't know here to store key"); + + if (strcasecmp(type, "rsa") != 0) + errx(1, "can only handle rsa keys for now"); + + e = BN_new(); + BN_set_word(e, 0x10001); + + if (optbits) + bits = optbits; + + rsa = RSA_new(); + if(rsa == NULL) + errx(1, "RSA_new failed"); + + ret = RSA_generate_key_ex(rsa, bits, e, NULL); + if(ret != 1) + errx(1, "RSA_new failed"); + + BN_free(e); + + len = i2d_RSAPrivateKey(rsa, NULL); + + p0 = p = malloc(len); + if (p == NULL) + errx(1, "out of memory"); + + i2d_RSAPrivateKey(rsa, &p); + + rk_dumpdata(fn, p0, len); + memset(p0, 0, len); + free(p0); + + RSA_free(rsa); + + } else if (fn == NULL) + err(1, "no private key"); + + ret = read_private_key(fn, signer); + if (ret) + err(1, "read_private_key"); +} + +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)); + + 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); + } + 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]); + } + + for (i = 0; i < opt->dnsname_strings.num_strings; i++) { + ret = _hx509_request_add_dns_name(context, req, + opt->dnsname_strings.strings[i]); + } + + + 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; + + ret = _hx509_request_parse(context, argv[i], &req); + if (ret) + hx509_err(context, 1, ret, "parse_request: %s", argv[i]); + + ret = _hx509_request_print(context, req, stdout); + _hx509_request_free(&req); + if (ret) + hx509_err(context, 1, ret, "Failed to print file %s", argv[i]); + } + + 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); + } + { + 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; + int len, 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; + + 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); + } else + type = HX509_SELECT_ALL; + + ret = hx509_crypto_available(context, type, NULL, &val, &len); + if (ret) + errx(1, "hx509_crypto_available"); + + for (i = 0; i < len; i++) { + char *s; + 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; + 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); + } else + type = HX509_SELECT_DIGEST; + + 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"); + + 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) != len) + errx(1, "fwrite failed"); + } + } else { + char buf[28], *p; + size_t len; + + while((len = fread(buf, 1, sizeof(buf), stdin)) != 0) { + len = hex_encode(buf, len, &p); + fprintf(stdout, "%s\n", p); + free(p); + } + } + return 0; +} + +static int +eval_types(hx509_context context, + hx509_ca_tbs tbs, + const struct certificate_sign_options *opt) +{ + int pkinit = 0; + int i, ret; + + for (i = 0; i < opt->type_strings.num_strings; i++) { + const char *type = opt->type_strings.strings[i]; + + if (strcmp(type, "https-server") == 0) { + ret = hx509_ca_tbs_add_eku(context, tbs, + oid_id_pkix_kp_serverAuth()); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); + } else if (strcmp(type, "https-client") == 0) { + ret = hx509_ca_tbs_add_eku(context, tbs, + oid_id_pkix_kp_clientAuth()); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); + } else if (strcmp(type, "peap-server") == 0) { + ret = hx509_ca_tbs_add_eku(context, tbs, + oid_id_pkix_kp_serverAuth()); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); + } else if (strcmp(type, "pkinit-kdc") == 0) { + pkinit++; + ret = hx509_ca_tbs_add_eku(context, tbs, + oid_id_pkkdcekuoid()); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); + } else if (strcmp(type, "pkinit-client") == 0) { + pkinit++; + ret = hx509_ca_tbs_add_eku(context, tbs, + oid_id_pkekuoid()); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); + + ret = hx509_ca_tbs_add_eku(context, tbs, + oid_id_ms_client_authentication()); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); + + ret = hx509_ca_tbs_add_eku(context, tbs, + oid_id_pkinit_ms_eku()); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); + + } else if (strcmp(type, "email") == 0) { + ret = hx509_ca_tbs_add_eku(context, tbs, + oid_id_pkix_kp_emailProtection()); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); + } else + errx(1, "unknown type %s", type); + } + + if (pkinit > 1) + errx(1, "More the one PK-INIT type given"); + + if (opt->pk_init_principal_string) { + if (!pkinit) + errx(1, "pk-init principal given but no pk-init oid"); + + ret = hx509_ca_tbs_add_san_pkinit(context, tbs, + opt->pk_init_principal_string); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_pkinit"); + } + + if (opt->ms_upn_string) { + if (!pkinit) + errx(1, "MS up given but no pk-init oid"); + + ret = hx509_ca_tbs_add_san_ms_upn(context, tbs, opt->ms_upn_string); + if (ret) + hx509_err(context, 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(context, tbs, hostname); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_hostname"); + } + + 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(context, tbs, email); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_hostname"); + + ret = hx509_ca_tbs_add_eku(context, tbs, + oid_id_pkix_kp_emailProtection()); + if (ret) + hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); + } + + if (opt->jid_string) { + ret = hx509_ca_tbs_add_san_jid(context, tbs, opt->jid_string); + if (ret) + hx509_err(context, 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; + int delta = 0; + + 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) { + if (opt->template_fields_string == NULL) + errx(1, "--template-certificate not no --template-fields"); + } + + 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; + + ret = hx509_certs_init(context, opt->ca_certificate_string, 0, + NULL, &cacerts); + if (ret) + hx509_err(context, 1, ret, + "hx509_certs_init: %s", opt->ca_certificate_string); + + 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"); + } else if (opt->self_signed_flag) { + if (opt->generate_key_string == NULL + && opt->ca_private_key_string == NULL) + errx(1, "no signing private key"); + } 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; + + ret = _hx509_request_parse(context, opt->req_string, &req); + if (ret) + hx509_err(context, 1, ret, "parse_request: %s", opt->req_string); + 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); + } + + if (opt->generate_key_string) { + struct hx509_generate_private_context *keyctx; + + ret = _hx509_generate_private_key_init(context, + oid_id_pkcs1_rsaEncryption(), + &keyctx); + + 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"); + + if (opt->template_certificate_string) { + hx509_cert template; + hx509_certs tcerts; + int flags; + + ret = hx509_certs_init(context, opt->template_certificate_string, 0, + NULL, &tcerts); + if (ret) + hx509_err(context, 1, ret, + "hx509_certs_init: %s", opt->template_certificate_string); + + 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); + } + + 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->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->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; + + ret = hx509_certs_init(context, opt->certificate_string, + 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); + } + + 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 +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, 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); + + for (i = 0; i < argc; i++) { + ret = hx509_certs_append(context, certs, lock, argv[i]); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_append"); + } + + 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(context, certs, test_one_cert, vctx); + + hx509_certs_free(&certs); + + 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; + + ret = hx509_certs_init(context, opt->signer_string, 0, + NULL, &certs); + if (ret) + hx509_err(context, 1, ret, + "hx509_certs_init: %s", opt->signer_string); + + 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"); + } + + 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); + + for (i = 0; i < argc; i++) { + ret = hx509_certs_append(context, revoked, lock, argv[i]); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_append: %s", argv[i]); + } + + 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 +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/crypto/heimdal/lib/hx509/keyset.c b/crypto/heimdal/lib/hx509/keyset.c new file mode 100644 index 0000000..2fcff7b --- /dev/null +++ b/crypto/heimdal/lib/hx509/keyset.c @@ -0,0 +1,677 @@ +/* + * 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" +RCSID("$Id: keyset.c 22466 2008-01-16 14:26:35Z lha $"); + +/** + * @page page_keyset Certificate store operations + * + * Type of certificates store: + * - MEMORY + * In memory based format. Doesnt 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 { + int ref; + struct hx509_keyset_ops *ops; + void *ops_data; +}; + +static 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; +} + +void +_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. + * @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(). + * + * @ingroup hx509_keyset + */ + +int +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; + + 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->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; +} + +/** + * Write the certificate store to stable storage. + * + * @param context A hx509 context. + * @param certs a certificate store to store. + * @param flags currently unused, use 0. + * @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 + */ + +int +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_certs +_hx509_certs_ref(hx509_certs certs) +{ + if (certs == NULL) + return NULL; + if (certs->ref <= 0) + _hx509_abort("certs refcount <= 0"); + certs->ref++; + if (certs->ref == 0) + _hx509_abort("certs refcount == 0"); + return certs; +} + +/** + * Free a certificate store. + * + * @param certs certificate store to free. + * + * @ingroup hx509_keyset + */ + +void +hx509_certs_free(hx509_certs *certs) +{ + if (*certs) { + if ((*certs)->ref <= 0) + _hx509_abort("refcount <= 0"); + 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 + */ + +int +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 + */ + +int +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 + */ + +int +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 an function + * for each fo 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 te caller of hx509_certs_iter(). + * @param ctx context variable that will passed to the function. + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + +int +hx509_certs_iter(hx509_context context, + hx509_certs certs, + int (*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; +} + + +/** + * Function to use to hx509_certs_iter() as a function argument, the + * ctx variable to hx509_certs_iter() should be a FILE file descriptor. + * + * @param context a hx509 context. + * @param ctx used by hx509_certs_iter(). + * @param c a certificate + * + * @return Returns an hx509 error code. + * + * @ingroup hx509_keyset + */ + +int +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 + */ + +int +hx509_certs_add(hx509_context context, hx509_certs certs, hx509_cert cert) +{ + 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; + } + + return (*certs->ops->add)(context, certs, certs->ops_data, cert); +} + +/** + * 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 + */ + +int +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; + break; + } + hx509_cert_free(c); + } + + hx509_certs_end_seq(context, certs, cursor); + if (ret) + return ret; + if (c == NULL) { + hx509_clear_error_string(context); + return HX509_CERT_NOT_FOUND; + } + + return 0; +} + +static int +certs_merge_func(hx509_context context, void *ctx, hx509_cert c) +{ + return hx509_certs_add(context, (hx509_certs)ctx, c); +} + +/** + * Merge a certificate store into another. The from store is keep + * 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 + */ + +int +hx509_certs_merge(hx509_context context, hx509_certs to, hx509_certs from) +{ + if (from == NULL) + return 0; + return hx509_certs_iter(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 + */ + +int +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 + */ + +int +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 + */ + +int +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); +} + +void +_hx509_pi_printf(int (*func)(void *, const char *), void *ctx, + const char *fmt, ...) +{ + va_list ap; + char *str; + + va_start(ap, fmt); + vasprintf(&str, fmt, ap); + va_end(ap); + if (str == NULL) + return; + (*func)(ctx, str); + free(str); +} + +int +_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); +} + +int +_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); +} + + +void +_hx509_certs_keys_free(hx509_context context, + hx509_private_key *keys) +{ + int i; + for (i = 0; keys[i]; i++) + _hx509_private_key_free(&keys[i]); + free(keys); +} diff --git a/crypto/heimdal/lib/hx509/ks_dir.c b/crypto/heimdal/lib/hx509/ks_dir.c new file mode 100644 index 0000000..a0bc875 --- /dev/null +++ b/crypto/heimdal/lib/hx509/ks_dir.c @@ -0,0 +1,223 @@ +/* + * 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" +RCSID("$Id: ks_dir.c 19778 2007-01-09 10:52:13Z lha $"); +#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; + + { + 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 ((sb.st_mode & S_IFDIR) == 0) { + 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; + } + 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 +}; + +void +_hx509_ks_dir_register(hx509_context context) +{ + _hx509_ks_register(context, &keyset_dir); +} diff --git a/crypto/heimdal/lib/hx509/ks_file.c b/crypto/heimdal/lib/hx509/ks_file.c new file mode 100644 index 0000000..87b97af --- /dev/null +++ b/crypto/heimdal/lib/hx509/ks_file.c @@ -0,0 +1,643 @@ +/* + * 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" +RCSID("$Id: ks_file.c 22465 2008-01-16 14:25:24Z lha $"); + +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, + struct hx509_collector *c, + const hx509_pem_header *headers, + const void *data, size_t len) +{ + hx509_cert cert; + int ret; + + ret = hx509_cert_init_data(context, data, len, &cert); + if (ret) + 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, + 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) { + hx509_set_error_string(context, 0, HX509_CRYPTO_INTERNAL_ERROR, + "Failed to do string2key for private key"); + return HX509_CRYPTO_INTERNAL_ERROR; + } + + 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); + } + + ret = _hx509_collector_private_key_add(context, + collector, + alg, + NULL, + &clear, + NULL); + + memset(clear.data, 0, clear.length); + free(clear.data); +out: + memset(key, 0, keylen); + free(key); + return ret; +} + +static int +parse_rsa_private_key(hx509_context context, const char *fn, + struct hx509_collector *c, + const hx509_pem_header *headers, + const void *data, size_t len) +{ + 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 i, decrypted = 0; + + 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, + "RSA 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 RSA 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, + "RSA 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 RSA 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, hx509_signature_rsa(), + 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, hx509_signature_rsa(), + cipher, ivdata, password, strlen(password), + data, len); + /* XXX add password to lock password collection ? */ + memset(password, 0, sizeof(password)); + } + free(ivdata); + + } else { + heim_octet_string keydata; + + keydata.data = rk_UNCONST(data); + keydata.length = len; + + ret = _hx509_collector_private_key_add(context, + c, + hx509_signature_rsa(), + NULL, + &keydata, + NULL); + } + + return ret; +} + + +struct pem_formats { + const char *name; + int (*func)(hx509_context, const char *, struct hx509_collector *, + const hx509_pem_header *, const void *, size_t); +} formats[] = { + { "CERTIFICATE", parse_certificate }, + { "RSA PRIVATE KEY", parse_rsa_private_key } +}; + + +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, j; + + for (j = 0; j < sizeof(formats)/sizeof(formats[0]); j++) { + const char *q = formats[j].name; + if (strcasecmp(type, q) == 0) { + ret = (*formats[j].func)(context, NULL, pem_ctx->c, header, data, len); + if (ret == 0) + 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; + } + if (ret && (pem_ctx->flags & HX509_CERTS_UNPROTECT_ALL)) + 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 *f = NULL; + hx509_private_key *keys = NULL; + int ret; + struct pem_ctx pem_ctx; + + pem_ctx.flags = flags; + pem_ctx.c = NULL; + + *data = NULL; + + if (lock == NULL) + lock = _hx509_empty_lock; + + f = calloc(1, sizeof(*f)); + if (f == NULL) { + hx509_clear_error_string(context); + return ENOMEM; + } + f->format = format; + + f->fn = strdup(residue); + if (f->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) { + ret = hx509_certs_init(context, "MEMORY:ks-file-create", + 0, lock, &f->certs); + if (ret) + goto out; + *data = f; + return 0; + } + + ret = _hx509_collector_alloc(context, lock, &pem_ctx.c); + if (ret) + goto out; + + for (p = f->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; + } + + 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; + int i; + + ret = _hx509_map_file(p, &ptr, &length, NULL); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + + for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) { + ret = (*formats[i].func)(context, p, pem_ctx.c, NULL, ptr, length); + if (ret == 0) + break; + } + _hx509_unmap_file(ptr, length); + if (ret) + goto out; + } + } + + ret = _hx509_collector_collect_certs(context, pem_ctx.c, &f->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, f->certs, keys[i]); + _hx509_certs_keys_free(context, keys); + } + +out: + if (ret == 0) + *data = f; + else { + if (f->fn) + free(f->fn); + free(f); + } + 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 *f = data; + hx509_certs_free(&f->certs); + free(f->fn); + free(f); + return 0; +} + +struct store_ctx { + FILE *f; + outformat format; +}; + +static int +store_func(hx509_context context, void *ctx, hx509_cert c) +{ + struct store_ctx *sc = ctx; + heim_octet_string data; + int ret; + + ret = hx509_cert_binary(context, c, &data); + if (ret) + return ret; + + switch (sc->format) { + case USE_DER: + fwrite(data.data, data.length, 1, sc->f); + free(data.data); + break; + case USE_PEM: + hx509_pem_write(context, "CERTIFICATE", NULL, sc->f, + data.data, data.length); + free(data.data); + if (_hx509_cert_private_key_exportable(c)) { + hx509_private_key key = _hx509_cert_private_key(c); + ret = _hx509_private_key_export(context, key, &data); + if (ret) + break; + hx509_pem_write(context, _hx509_private_pem_name(key), NULL, sc->f, + data.data, data.length); + free(data.data); + } + break; + } + + return 0; +} + +static int +file_store(hx509_context context, + hx509_certs certs, void *data, int flags, hx509_lock lock) +{ + struct ks_file *f = data; + struct store_ctx sc; + int ret; + + sc.f = fopen(f->fn, "w"); + if (sc.f == NULL) { + hx509_set_error_string(context, 0, ENOENT, + "Failed to open file %s for writing"); + return ENOENT; + } + sc.format = f->format; + + ret = hx509_certs_iter(context, f->certs, store_func, &sc); + fclose(sc.f); + return ret; +} + +static int +file_add(hx509_context context, hx509_certs certs, void *data, hx509_cert c) +{ + struct ks_file *f = data; + return hx509_certs_add(context, f->certs, c); +} + +static int +file_iter_start(hx509_context context, + hx509_certs certs, void *data, void **cursor) +{ + struct ks_file *f = data; + return hx509_certs_start_seq(context, f->certs, cursor); +} + +static int +file_iter(hx509_context context, + hx509_certs certs, void *data, void *iter, hx509_cert *cert) +{ + struct ks_file *f = data; + return hx509_certs_next_cert(context, f->certs, iter, cert); +} + +static int +file_iter_end(hx509_context context, + hx509_certs certs, + void *data, + void *cursor) +{ + struct ks_file *f = data; + return hx509_certs_end_seq(context, f->certs, cursor); +} + +static int +file_getkeys(hx509_context context, + hx509_certs certs, + void *data, + hx509_private_key **keys) +{ + struct ks_file *f = data; + return _hx509_certs_keys_get(context, f->certs, keys); +} + +static int +file_addkey(hx509_context context, + hx509_certs certs, + void *data, + hx509_private_key key) +{ + struct ks_file *f = data; + return _hx509_certs_keys_add(context, f->certs, key); +} + +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 +}; + +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 +}; + +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 +}; + + +void +_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/crypto/heimdal/lib/hx509/ks_keychain.c b/crypto/heimdal/lib/hx509/ks_keychain.c new file mode 100644 index 0000000..f818197 --- /dev/null +++ b/crypto/heimdal/lib/hx509/ks_keychain.c @@ -0,0 +1,548 @@ +/* + * 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" +RCSID("$Id: ks_keychain.c 22084 2007-11-16 20:12:30Z lha $"); + +#ifdef HAVE_FRAMEWORK_SECURITY + +#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 +#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; + + + 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) +{ + return -1; +} + +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 +}; + +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; + + 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); + return ENOENT; + } + } else { + hx509_set_error_string(context, 0, ENOENT, + "Unknown subtype %s", residue); + 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); + + ret = hx509_cert_init_data(context, cssm.Data, cssm.Length, &cert); + if (ret) + 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]; + 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; + + ret = hx509_cert_init_data(context, ptr, len, cert); + if (ret) + 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) { + int ret; + ret = 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 +}; + +#endif /* HAVE_FRAMEWORK_SECURITY */ + +/* + * + */ + +void +_hx509_ks_keychain_register(hx509_context context) +{ +#ifdef HAVE_FRAMEWORK_SECURITY + _hx509_ks_register(context, &keyset_keychain); +#endif +} diff --git a/crypto/heimdal/lib/hx509/ks_mem.c b/crypto/heimdal/lib/hx509/ks_mem.c new file mode 100644 index 0000000..efa19eb --- /dev/null +++ b/crypto/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" +RCSID("Id$"); + +/* + * 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++] = 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 +}; + +void +_hx509_ks_mem_register(hx509_context context) +{ + _hx509_ks_register(context, &keyset_mem); +} diff --git a/crypto/heimdal/lib/hx509/ks_null.c b/crypto/heimdal/lib/hx509/ks_null.c new file mode 100644 index 0000000..3be259f --- /dev/null +++ b/crypto/heimdal/lib/hx509/ks_null.c @@ -0,0 +1,98 @@ +/* + * 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" +RCSID("$Id: ks_null.c 20901 2007-06-04 23:14:08Z lha $"); + + +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 +}; + +void +_hx509_ks_null_register(hx509_context context) +{ + _hx509_ks_register(context, &keyset_null); +} diff --git a/crypto/heimdal/lib/hx509/ks_p11.c b/crypto/heimdal/lib/hx509/ks_p11.c new file mode 100644 index 0000000..0d7c312 --- /dev/null +++ b/crypto/heimdal/lib/hx509/ks_p11.c @@ -0,0 +1,1192 @@ +/* + * 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. + */ + +#include "hx_locl.h" +RCSID("$Id: ks_p11.c 22071 2007-11-14 20:04:50Z lha $"); +#ifdef HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#ifdef HAVE_DLOPEN + +#include "pkcs11.h" + +struct p11_slot { + int 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 refcount; + 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 *)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 *)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 +}; + +/* + * + */ + +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; + int ret, i; + + 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; + } + + asprintf(&slot->name, "%.*s", + i, slot_info.slotDescription); + + 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 0x08x", + 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; + + slot->flags |= P11_LOGIN_DONE; + + if (slot->pin == NULL) { + + memset(&prompt, 0, sizeof(prompt)); + + asprintf(&str, "PIN code for %s: ", slot->name); + 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); + p11_put_session(p, slot, slot->session); + return HX509_PKCS11_LOGIN; + } + if (slot->pin == NULL) { + slot->pin = strdup(pin); + if (slot->pin == NULL) { + if (context) + hx509_set_error_string(context, 0, ENOMEM, + "out of memory"); + p11_put_session(p, slot, slot->session); + 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, 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; + } + + ret = P11FUNC(p, FindObjectsFinal, (session)); + if (ret != CKR_OK) { + return -2; + } + + + return 0; +} + +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; + + p->refcount++; + if (p->refcount == 0) + _hx509_abort("pkcs11 refcount to high"); + + 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; + hx509_cert cert; + int ret; + + if ((CK_LONG)query[0].ulValueLen == -1 || + (CK_LONG)query[1].ulValueLen == -1) + { + return 0; + } + + ret = hx509_cert_init_data(context, query[1].pValue, + query[1].ulValueLen, &cert); + if (ret) + return ret; + + p->refcount++; + if (p->refcount == 0) + _hx509_abort("pkcs11 refcount 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, + oid_id_pkcs_9_at_localKeyId(), + &data); + } + + if ((CK_LONG)query[2].ulValueLen != -1) { + char *str; + + asprintf(&str, "%.*s", + (int)query[2].ulValueLen, (char *)query[2].pValue); + if (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; + + list = strdup(residue); + if (list == NULL) + return ENOMEM; + + p = calloc(1, sizeof(*p)); + if (p == NULL) { + free(list); + return ENOMEM; + } + + p->refcount = 1; + + str = strchr(list, ','); + if (str) + *str++ = '\0'; + while (str) { + char *strnext; + strnext = strchr(str, ','); + if (strnext) + *strnext++ = '\0'; +#if 0 + if (strncasecmp(str, "slot=", 5) == 0) + p->selected_slot = atoi(str + 5); +#endif + str = strnext; + } + + p->dl_handle = dlopen(list, RTLD_NOW); + free(list); + 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 = 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 i, num_tokens = 0; + + 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++) { + ret = p11_init_slot(context, p, lock, slot_ids[i], i, &p->slot[i]); + if (ret) + break; + 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; + } + } + + *data = p; + + return 0; + out: + p11_release_module(p); + return ret; +} + +static void +p11_release_module(struct p11_module *p) +{ + int i; + + if (p->refcount == 0) + _hx509_abort("pkcs11 refcount to low"); + if (--p->refcount > 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) { + int ret; + + ret = P11FUNC(p, CloseSession, (p->slot[i].session)); + if (ret != CKR_OK) + ; + } + + 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) { + int 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; + int 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, 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; + int 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_MD2, "md2"); + 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 +}; + +#endif /* HAVE_DLOPEN */ + +void +_hx509_ks_pkcs11_register(hx509_context context) +{ +#ifdef HAVE_DLOPEN + _hx509_ks_register(context, &keyset_pkcs11); +#endif +} diff --git a/crypto/heimdal/lib/hx509/ks_p12.c b/crypto/heimdal/lib/hx509/ks_p12.c new file mode 100644 index 0000000..12756e6 --- /dev/null +++ b/crypto/heimdal/lib/hx509/ks_p12.c @@ -0,0 +1,704 @@ +/* + * 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" +RCSID("$Id: ks_p12.c 21146 2007-06-18 21:37:25Z lha $"); + +struct ks_pkcs12 { + hx509_certs certs; + char *fn; +}; + +typedef int (*collector_func)(hx509_context, + struct hx509_collector *, + const void *, size_t, + const PKCS12_Attributes *); + +struct type { + const heim_oid * (*oid)(void); + collector_func func; +}; + +static void +parse_pkcs12_type(hx509_context, struct hx509_collector *, const heim_oid *, + const void *, size_t, const PKCS12_Attributes *); + + +static const PKCS12_Attribute * +find_attribute(const PKCS12_Attributes *attrs, const heim_oid *oid) +{ + int 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, + const void *data, size_t length, + const PKCS12_Attributes *attrs) +{ + const PKCS12_Attribute *attr; + PKCS8PrivateKeyInfo ki; + const heim_octet_string *os = NULL; + int ret; + + attr = find_attribute(attrs, 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, + 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, content.data, content.length, attrs); + der_free_octet_string(&content); + return ret; +} + +static int +certBag_parser(hx509_context context, + struct hx509_collector *c, + const void *data, size_t length, + const PKCS12_Attributes *attrs) +{ + 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(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; + + ret = hx509_cert_init_data(context, os.data, os.length, &cert); + der_free_octet_string(&os); + if (ret) + 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[])(void) = { + oid_id_pkcs_9_at_localKeyId, oid_id_pkcs_9_at_friendlyName + }; + int 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, + const unsigned char *p, size_t len) +{ + PKCS12_SafeContents sc; + int ret, 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, + &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, + 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, os.data, os.length); + der_free_octet_string(&os); + return ret; +} + +static int +encryptedData_parser(hx509_context context, + struct hx509_collector *c, + 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, oid_id_pkcs7_data()) == 0) + ret = parse_safe_content(context, c, 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, + 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, + &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, oid_id_pkcs7_data()) == 0) + ret = parse_safe_content(context, c, content.data, content.length); + + der_free_octet_string(&content); + der_free_oid(&contentType); + + return ret; +} + + +struct type bagtypes[] = { + { oid_id_pkcs12_keyBag, keyBag_parser }, + { oid_id_pkcs12_pkcs8ShroudedKeyBag, ShroudedKeyBag_parser }, + { oid_id_pkcs12_certBag, certBag_parser }, + { oid_id_pkcs7_data, safeContent_parser }, + { oid_id_pkcs7_encryptedData, encryptedData_parser }, + { oid_id_pkcs7_envelopedData, envelopedData_parser } +}; + +static void +parse_pkcs12_type(hx509_context context, + struct hx509_collector *c, + const heim_oid *oid, + const void *data, size_t length, + const PKCS12_Attributes *attrs) +{ + int 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, 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, i; + struct hx509_collector *c; + + *data = NULL; + + 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 = _hx509_map_file(residue, &buf, &len, NULL); + if (ret) { + hx509_clear_error_string(context); + goto out; + } + + ret = decode_PKCS12_PFX(buf, len, &pfx, NULL); + _hx509_unmap_file(buf, len); + 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, 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, + &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; +} + +static int +store_func(hx509_context context, void *ctx, hx509_cert c) +{ + PKCS12_AuthenticatedSafe *as = ctx; + 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(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, as, oid_id_pkcs12_certBag(), os.data, os.length); + + if (_hx509_cert_private_key_exportable(c)) { + 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), + &pki.privateKey); + if (ret) { + free_PKCS8PrivateKeyInfo(&pki); + return ret; + } + /* set attribute, 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, as, 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; + PKCS12_AuthenticatedSafe as; + PKCS12_OctetString asdata; + size_t size; + int ret; + + memset(&as, 0, sizeof(as)); + memset(&pfx, 0, sizeof(pfx)); + + ret = hx509_certs_iter(context, p12->certs, store_func, &as); + if (ret) + goto out; + + ASN1_MALLOC_ENCODE(PKCS12_AuthenticatedSafe, asdata.data, asdata.length, + &as, &size, ret); + free_PKCS12_AuthenticatedSafe(&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(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(&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 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 +}; + +void +_hx509_ks_pkcs12_register(hx509_context context) +{ + _hx509_ks_register(context, &keyset_pkcs12); +} diff --git a/crypto/heimdal/lib/hx509/lock.c b/crypto/heimdal/lib/hx509/lock.c new file mode 100644 index 0000000..e835aee --- /dev/null +++ b/crypto/heimdal/lib/hx509/lock.c @@ -0,0 +1,248 @@ +/* + * 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" +RCSID("$Id: lock.c 22327 2007-12-15 04:49:37Z lha $"); + +/** + * @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 } +}; + +hx509_lock _hx509_empty_lock = &empty_lock_data; + +/* + * + */ + +int +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; +} + +int +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; +} + +const struct _hx509_password * +_hx509_lock_get_passwords(hx509_lock lock) +{ + return &lock->password; +} + +hx509_certs +_hx509_lock_unlock_certs(hx509_lock lock) +{ + return lock->certs; +} + +void +hx509_lock_reset_passwords(hx509_lock lock) +{ + int 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; +} + +int +hx509_lock_add_cert(hx509_context context, hx509_lock lock, hx509_cert cert) +{ + return hx509_certs_add(context, lock->certs, cert); +} + +int +hx509_lock_add_certs(hx509_context context, hx509_lock lock, hx509_certs certs) +{ + return hx509_certs_merge(context, lock->certs, certs); +} + +void +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; +} + +int +_hx509_lock_find_cert(hx509_lock lock, const hx509_query *q, hx509_cert *c) +{ + *c = NULL; + return 0; +} + +int +hx509_lock_set_prompter(hx509_lock lock, hx509_prompter_fct prompt, void *data) +{ + lock->prompt = prompt; + lock->prompt_data = data; + return 0; +} + +void +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; +} + +int +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); +} + +void +hx509_lock_free(hx509_lock lock) +{ + hx509_certs_free(&lock->certs); + hx509_lock_reset_passwords(lock); + memset(lock, 0, sizeof(*lock)); + free(lock); +} + +int +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; + } +} + +int +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/crypto/heimdal/lib/hx509/name.c b/crypto/heimdal/lib/hx509/name.c new file mode 100644 index 0000000..69fafe1 --- /dev/null +++ b/crypto/heimdal/lib/hx509/name.c @@ -0,0 +1,918 @@ +/* + * 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" +RCSID("$Id: name.c 22432 2008-01-13 14:08:03Z lha $"); + +/** + * @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 serveral 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)(void); +} no[] = { + { "C", oid_id_at_countryName }, + { "CN", oid_id_at_commonName }, + { "DC", oid_id_domainComponent }, + { "L", oid_id_at_localityName }, + { "O", oid_id_at_organizationName }, + { "OU", oid_id_at_organizationalUnitName }, + { "S", oid_id_at_stateOrProvinceName }, + { "STREET", oid_id_at_streetAddress }, + { "UID", oid_id_Userid }, + { "emailAddress", oid_id_pkcs9_emailAddress }, + { "serialNumber", oid_id_at_serialNumber } +}; + +static char * +quote_string(const char *f, size_t len, size_t *rlen) +{ + size_t i, j, tolen; + const char *from = f; + char *to; + + tolen = len * 3 + 1; + to = malloc(tolen); + if (to == NULL) + return NULL; + + for (i = 0, j = 0; i < len; i++) { + if (from[i] == ' ' && i + 1 < len) + to[j++] = from[i]; + else if (from[i] == ',' || from[i] == '=' || from[i] == '+' || + from[i] == '<' || from[i] == '>' || from[i] == '#' || + from[i] == ';' || from[i] == ' ') + { + to[j++] = '\\'; + to[j++] = from[i]; + } else if (((unsigned char)from[i]) >= 32 && ((unsigned char)from[i]) <= 127) { + to[j++] = from[i]; + } else { + int l = snprintf(&to[j], tolen - j - 1, + "#%02x", (unsigned char)from[i]); + j += l; + } + } + to[j] = '\0'; + assert(j < tolen); + *rlen = j; + return 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, &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) +{ + char *s; + size_t i; + + for (i = 0; i < sizeof(no)/sizeof(no[0]); i++) { + if (der_heim_oid_cmp((*no[i].o)(), type) == 0) + return strdup(no[i].n); + } + if (der_print_heim_oid(type, '.', &s) != 0) + return NULL; + return s; +} + +static int +stringtooid(const char *name, size_t len, heim_oid *oid) +{ + int i, ret; + 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 + */ + +int +hx509_name_to_string(const hx509_name name, char **str) +{ + return _hx509_Name_to_string(&name->der_name, str); +} + +int +_hx509_Name_to_string(const Name *n, char **str) +{ + size_t total_len = 0; + int i, j; + + *str = strdup(""); + if (*str == NULL) + return ENOMEM; + + for (i = n->u.rdnSequence.len - 1 ; i >= 0 ; i--) { + int len; + + 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); + + switch(ds->element) { + case choice_DirectoryString_ia5String: + ss = ds->u.ia5String; + break; + case choice_DirectoryString_printableString: + ss = ds->u.printableString; + break; + case choice_DirectoryString_utf8String: + ss = ds->u.utf8String; + break; + case choice_DirectoryString_bmpString: { + uint16_t *bmp = ds->u.bmpString.data; + size_t bmplen = ds->u.bmpString.length; + size_t k; + + ss = malloc(bmplen + 1); + if (ss == NULL) + _hx509_abort("allocation failure"); /* XXX */ + for (k = 0; k < bmplen; k++) + ss[k] = bmp[k] & 0xff; /* XXX */ + ss[k] = '\0'; + break; + } + case choice_DirectoryString_teletexString: + ss = malloc(ds->u.teletexString.length + 1); + if (ss == NULL) + _hx509_abort("allocation failure"); /* XXX */ + memcpy(ss, ds->u.teletexString.data, ds->u.teletexString.length); + ss[ds->u.teletexString.length] = '\0'; + break; + case choice_DirectoryString_universalString: { + uint32_t *uni = ds->u.universalString.data; + size_t unilen = ds->u.universalString.length; + size_t k; + + ss = malloc(unilen + 1); + if (ss == NULL) + _hx509_abort("allocation failure"); /* XXX */ + for (k = 0; k < unilen; k++) + ss[k] = uni[k] & 0xff; /* XXX */ + ss[k] = '\0'; + 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); + len = strlen(ss); + append_string(str, &total_len, ss, len, 1); + if (ds->element == choice_DirectoryString_universalString || + ds->element == choice_DirectoryString_bmpString || + ds->element == choice_DirectoryString_teletexString) + { + 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; +} + +/* + * XXX this function is broken, it needs to compare code points, not + * bytes. + */ + +static void +prune_space(const unsigned char **s) +{ + while (**s == ' ') + (*s)++; +} + +int +_hx509_name_ds_cmp(const DirectoryString *ds1, const DirectoryString *ds2) +{ + int c; + + c = ds1->element - ds2->element; + if (c) + return c; + + switch(ds1->element) { + case choice_DirectoryString_ia5String: + c = strcmp(ds1->u.ia5String, ds2->u.ia5String); + break; + case choice_DirectoryString_teletexString: + c = der_heim_octet_string_cmp(&ds1->u.teletexString, + &ds2->u.teletexString); + break; + case choice_DirectoryString_printableString: { + const unsigned char *s1 = (unsigned char*)ds1->u.printableString; + const unsigned char *s2 = (unsigned char*)ds2->u.printableString; + prune_space(&s1); prune_space(&s2); + while (*s1 && *s2) { + if (toupper(*s1) != toupper(*s2)) { + c = toupper(*s1) - toupper(*s2); + break; + } + if (*s1 == ' ') { prune_space(&s1); prune_space(&s2); } + else { s1++; s2++; } + } + prune_space(&s1); prune_space(&s2); + c = *s1 - *s2; + break; + } + case choice_DirectoryString_utf8String: + c = strcmp(ds1->u.utf8String, ds2->u.utf8String); + break; + case choice_DirectoryString_universalString: + c = der_heim_universal_string_cmp(&ds1->u.universalString, + &ds2->u.universalString); + break; + case choice_DirectoryString_bmpString: + c = der_heim_bmp_string_cmp(&ds1->u.bmpString, + &ds2->u.bmpString); + break; + default: + c = 1; + break; + } + return c; +} + +int +_hx509_name_cmp(const Name *n1, const Name *n2) +{ + int i, j, c; + + c = n1->u.rdnSequence.len - n2->u.rdnSequence.len; + if (c) + return c; + + 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 c; + + 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 c; + + c = _hx509_name_ds_cmp(&n1->u.rdnSequence.val[i].val[j].value, + &n2->u.rdnSequence.val[i].val[j].value); + if (c) + return c; + } + } + 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 + */ + +int +hx509_name_cmp(hx509_name n1, hx509_name n2) +{ + return _hx509_name_cmp(&n1->der_name, &n2->der_name); +} + + +int +_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; +} + +int +_hx509_name_modify(hx509_context context, + Name *name, + int append, + const heim_oid *oid, + const char *str) +{ + RelativeDistinguishedName *rdn; + int ret; + void *ptr; + + ptr = realloc(name->u.rdnSequence.val, + sizeof(name->u.rdnSequence.val[0]) * + (name->u.rdnSequence.len + 1)); + if (ptr == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "Out of memory"); + return ENOMEM; + } + name->u.rdnSequence.val = ptr; + + if (append) { + rdn = &name->u.rdnSequence.val[name->u.rdnSequence.len]; + } else { + memmove(&name->u.rdnSequence.val[1], + &name->u.rdnSequence.val[0], + name->u.rdnSequence.len * + sizeof(name->u.rdnSequence.val[0])); + + rdn = &name->u.rdnSequence.val[0]; + } + rdn->val = malloc(sizeof(rdn->val[0])); + if (rdn->val == NULL) + return ENOMEM; + rdn->len = 1; + ret = der_copy_oid(oid, &rdn->val[0].type); + if (ret) + return ret; + rdn->val[0].value.element = choice_DirectoryString_utf8String; + rdn->val[0].value.u.utf8String = strdup(str); + if (rdn->val[0].value.u.utf8String == NULL) + return ENOMEM; + name->u.rdnSequence.len += 1; + + 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 + */ + +int +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 ((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 + */ + +int +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 + */ + +int +hx509_name_to_Name(const hx509_name from, Name *to) +{ + return copy_Name(&from->der_name, to); +} + +int +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 + */ + +int +hx509_name_expand(hx509_context context, + hx509_name name, + hx509_env env) +{ + Name *n = &name->der_name; + int i, j; + + 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; + char *p, *p2; + struct rk_strpool *strpool = NULL; + + if (ds->element != choice_DirectoryString_utf8String) { + hx509_set_error_string(context, 0, EINVAL, "unsupported type"); + return EINVAL; + } + p = strstr(ds->u.utf8String, "${"); + if (p) { + strpool = rk_strpoolprintf(strpool, "%.*s", + (int)(p - ds->u.utf8String), + ds->u.utf8String); + if (strpool == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + 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); + 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); + return EINVAL; + } + strpool = rk_strpoolprintf(strpool, "%s", value); + if (strpool == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + 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"); + return ENOMEM; + } + } + if (strpool) { + free(ds->u.utf8String); + ds->u.utf8String = rk_strpoolcollect(strpool); + if (ds->u.utf8String == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + } + } + } + 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 + */ + +void +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 + */ + +int +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 + */ + +int +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; +} + +int +_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; +} + +/** + * Unparse the hx509 name in name into a string. + * + * @param name the name to check if its empty/null. + * + * @return non zero if the name is empty/null. + * + * @ingroup hx509_name + */ + +int +hx509_name_is_null_p(const hx509_name name) +{ + return name->der_name.u.rdnSequence.len == 0; +} + +/** + * 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 krb5_get_error_string(). + * + * @ingroup hx509_name + */ + +int +hx509_general_name_unparse(GeneralName *name, char **str) +{ + struct rk_strpool *strpool = NULL; + + *str = NULL; + + switch (name->element) { + case choice_GeneralName_otherName: { + char *str; + hx509_oid_sprint(&name->u.otherName.type_id, &str); + if (str == NULL) + return ENOMEM; + strpool = rk_strpoolprintf(strpool, "otherName: %s", str); + free(str); + break; + } + case choice_GeneralName_rfc822Name: + strpool = rk_strpoolprintf(strpool, "rfc822Name: %s\n", + name->u.rfc822Name); + break; + case choice_GeneralName_dNSName: + strpool = rk_strpoolprintf(strpool, "dNSName: %s\n", + name->u.dNSName); + break; + case choice_GeneralName_directoryName: { + Name dir; + char *s; + int ret; + memset(&dir, 0, sizeof(dir)); + dir.element = 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", + name->u.uniformResourceIdentifier); + 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 *str; + hx509_oid_sprint(&name->u.registeredID, &str); + if (str == NULL) + return ENOMEM; + strpool = rk_strpoolprintf(strpool, "registeredID: %s", str); + free(str); + break; + } + default: + return EINVAL; + } + if (strpool == NULL) + return ENOMEM; + + *str = rk_strpoolcollect(strpool); + + return 0; +} diff --git a/crypto/heimdal/lib/hx509/ocsp.asn1 b/crypto/heimdal/lib/hx509/ocsp.asn1 new file mode 100644 index 0000000..d8ecd66 --- /dev/null +++ b/crypto/heimdal/lib/hx509/ocsp.asn1 @@ -0,0 +1,113 @@ +-- From rfc2560 +-- $Id: ocsp.asn1 19576 2006-12-30 12:40:43Z lha $ +OCSP DEFINITIONS EXPLICIT TAGS::= + +BEGIN + +IMPORTS + Certificate, AlgorithmIdentifier, CRLReason, + Name, GeneralName, CertificateSerialNumber, Extensions + FROM rfc2459; + +OCSPVersion ::= INTEGER { ocsp-v1(0) } + +OCSPCertStatus ::= CHOICE { + good [0] IMPLICIT NULL, + revoked [1] IMPLICIT -- OCSPRevokedInfo -- SEQUENCE { + revocationTime GeneralizedTime, + revocationReason[0] EXPLICIT CRLReason OPTIONAL + }, + unknown [2] IMPLICIT NULL } + +OCSPCertID ::= SEQUENCE { + hashAlgorithm AlgorithmIdentifier, + issuerNameHash OCTET STRING, -- Hash of Issuer's DN + issuerKeyHash OCTET STRING, -- Hash of Issuers public key + serialNumber CertificateSerialNumber } + +OCSPSingleResponse ::= SEQUENCE { + certID OCSPCertID, + certStatus OCSPCertStatus, + thisUpdate GeneralizedTime, + nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, + singleExtensions [1] EXPLICIT Extensions OPTIONAL } + +OCSPInnerRequest ::= SEQUENCE { + reqCert OCSPCertID, + singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } + +OCSPTBSRequest ::= SEQUENCE { + version [0] EXPLICIT OCSPVersion -- DEFAULT v1 -- OPTIONAL, + requestorName [1] EXPLICIT GeneralName OPTIONAL, + requestList SEQUENCE OF OCSPInnerRequest, + requestExtensions [2] EXPLICIT Extensions OPTIONAL } + +OCSPSignature ::= SEQUENCE { + signatureAlgorithm AlgorithmIdentifier, + signature BIT STRING, + certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } + +OCSPRequest ::= SEQUENCE { + tbsRequest OCSPTBSRequest, + optionalSignature [0] EXPLICIT OCSPSignature OPTIONAL } + +OCSPResponseBytes ::= SEQUENCE { + responseType OBJECT IDENTIFIER, + response OCTET STRING } + +OCSPResponseStatus ::= ENUMERATED { + successful (0), --Response has valid confirmations + malformedRequest (1), --Illegal confirmation request + internalError (2), --Internal error in issuer + tryLater (3), --Try again later + --(4) is not used + sigRequired (5), --Must sign the request + unauthorized (6) --Request unauthorized +} + +OCSPResponse ::= SEQUENCE { + responseStatus OCSPResponseStatus, + responseBytes [0] EXPLICIT OCSPResponseBytes OPTIONAL } + +OCSPKeyHash ::= OCTET STRING --SHA-1 hash of responder's public key + --(excluding the tag and length fields) + +OCSPResponderID ::= CHOICE { + byName [1] Name, + byKey [2] OCSPKeyHash } + +OCSPResponseData ::= SEQUENCE { + version [0] EXPLICIT OCSPVersion -- DEFAULT v1 -- OPTIONAL, + responderID OCSPResponderID, + producedAt GeneralizedTime, + responses SEQUENCE OF OCSPSingleResponse, + responseExtensions [1] EXPLICIT Extensions OPTIONAL } + +OCSPBasicOCSPResponse ::= SEQUENCE { + tbsResponseData OCSPResponseData, + signatureAlgorithm AlgorithmIdentifier, + signature BIT STRING, + certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } + +-- ArchiveCutoff ::= GeneralizedTime + +-- AcceptableResponses ::= SEQUENCE OF OBJECT IDENTIFIER + +-- Object Identifiers + +id-pkix-ocsp OBJECT IDENTIFIER ::= { + iso(1) identified-organization(3) dod(6) internet(1) + security(5) mechanisms(5) pkix(7) pkix-ad(48) 1 +} + +id-pkix-ocsp-basic OBJECT IDENTIFIER ::= { id-pkix-ocsp 1 } +id-pkix-ocsp-nonce OBJECT IDENTIFIER ::= { id-pkix-ocsp 2 } +-- id-pkix-ocsp-crl OBJECT IDENTIFIER ::= { id-pkix-ocsp 3 } +-- id-pkix-ocsp-response OBJECT IDENTIFIER ::= { id-pkix-ocsp 4 } +-- id-pkix-ocsp-nocheck OBJECT IDENTIFIER ::= { id-pkix-ocsp 5 } +-- id-pkix-ocsp-archive-cutoff OBJECT IDENTIFIER ::= { id-pkix-ocsp 6 } +-- id-pkix-ocsp-service-locator OBJECT IDENTIFIER ::= { id-pkix-ocsp 7 } + + +END + diff --git a/crypto/heimdal/lib/hx509/peer.c b/crypto/heimdal/lib/hx509/peer.c new file mode 100644 index 0000000..eb0ecd2 --- /dev/null +++ b/crypto/heimdal/lib/hx509/peer.c @@ -0,0 +1,202 @@ +/* + * 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" +RCSID("$Id: peer.c 22345 2007-12-26 19:03:51Z lha $"); + +/** + * @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 + */ + +int +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 + */ + +void +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 + */ + +int +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; +} + +/** + * 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 + */ + +int +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 + */ + +int +hx509_peer_info_parse_smime(hx509_peer_info peer, + const heim_octet_string *data) +{ + return 0; +} + +int +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. + */ + +int +hx509_peer_info_parse(hx509_peer_info peer, + const heim_octet_string *data) +{ + return 0; +} + +int +hx509_peer_info_unparse(hx509_peer_info peer, + heim_octet_string *data) +{ + return 0; +} +#endif diff --git a/crypto/heimdal/lib/hx509/pkcs10.asn1 b/crypto/heimdal/lib/hx509/pkcs10.asn1 new file mode 100644 index 0000000..518fe3b --- /dev/null +++ b/crypto/heimdal/lib/hx509/pkcs10.asn1 @@ -0,0 +1,25 @@ +-- $Id: pkcs10.asn1 16918 2006-04-01 09:46:57Z lha $ +PKCS10 DEFINITIONS ::= + +BEGIN + +IMPORTS + Name, SubjectPublicKeyInfo, Attribute, AlgorithmIdentifier + FROM rfc2459; + + +CertificationRequestInfo ::= SEQUENCE { + version INTEGER { pkcs10-v1(0) }, + subject Name, + subjectPKInfo SubjectPublicKeyInfo, + attributes [0] IMPLICIT SET OF Attribute OPTIONAL +} + +CertificationRequest ::= SEQUENCE { + certificationRequestInfo CertificationRequestInfo, + signatureAlgorithm AlgorithmIdentifier, + signature BIT STRING +} + +END + diff --git a/crypto/heimdal/lib/hx509/print.c b/crypto/heimdal/lib/hx509/print.c new file mode 100644 index 0000000..78ebbaf --- /dev/null +++ b/crypto/heimdal/lib/hx509/print.c @@ -0,0 +1,990 @@ +/* + * 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" +RCSID("$Id: print.c 22420 2008-01-13 09:42:35Z lha $"); + +/** + * @page page_print Hx509 printing functions + * + * See the library functions here: @ref hx509_print + */ + +struct hx509_validate_ctx_data { + 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 + */ + +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 + */ + +int +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 + */ + +void +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 + */ + +void +hx509_bitstring_print(const heim_bit_string *b, + hx509_vprint_func func, void *ctx) +{ + int 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 + */ + +int +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); +} + +/* + * Dont 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); + + status->haveSKI = 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); + } + } + + return 0; +} + + +static int +check_pkinit_san(hx509_validate_ctx ctx, heim_any *a) +{ + KRB5PrincipalName kn; + unsigned i; + size_t size; + int ret; + + ret = decode_KRB5PrincipalName(a->data, a->length, &kn, &size); + if (ret) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Decoding kerberos name in SAN failed: %d", ret); + return 1; + } + + if (size != a->length) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Decoding kerberos name have extra bits on the end"); + return 1; + } + + /* print kerberos principal, add code to quote / within components */ + for (i = 0; i < kn.principalName.name_string.len; i++) { + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "%s", + kn.principalName.name_string.val[i]); + if (i + 1 < kn.principalName.name_string.len) + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "/"); + } + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "@"); + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "%s", kn.realm); + + free_KRB5PrincipalName(&kn); + return 0; +} + +static int +check_utf8_string_san(hx509_validate_ctx ctx, heim_any *a) +{ + PKIXXmppAddr jid; + size_t size; + int ret; + + ret = decode_PKIXXmppAddr(a->data, a->length, &jid, &size); + if (ret) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Decoding JID in SAN failed: %d", ret); + return 1; + } + + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "%s", jid); + free_PKIXXmppAddr(&jid); + + return 0; +} + +static int +check_altnull(hx509_validate_ctx ctx, heim_any *a) +{ + 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, 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; + heim_any *data = dp.val[i].distributionPoint; + int j; + + ret = decode_DistributionPointName(data->data, data->length, + &dpname, NULL); + if (ret) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Failed to parse CRL Distribution Point Name: %d\n", ret); + continue; + } + + 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_unparse(name, &s); + if (ret == 0 && s != NULL) { + 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_DistributionPointName(&dpname); + } + } + free_CRLDistributionPoints(&dp); + + status->haveCRLDP = 1; + + return 0; +} + + +struct { + const char *name; + const heim_oid *(*oid)(void); + int (*func)(hx509_validate_ctx, heim_any *); +} check_altname[] = { + { "pk-init", oid_id_pkinit_san, check_pkinit_san }, + { "jabber", oid_id_pkix_on_xmppAddr, check_utf8_string_san }, + { "dns-srv", oid_id_pkix_on_dnsSRV, check_altnull }, + { "card-id", oid_id_uspkicommon_card_id, check_altnull }, + { "Microsoft NT-PRINCIPAL-NAME", oid_id_pkinit_ms_san, check_utf8_string_san } +}; + +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, 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++) { + switch (gn.val[i].element) { + case choice_GeneralName_otherName: { + unsigned j; + + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + "%sAltName otherName ", name); + + for (j = 0; j < sizeof(check_altname)/sizeof(check_altname[0]); j++) { + if (der_heim_oid_cmp((*check_altname[j].oid)(), + &gn.val[i].u.otherName.type_id) != 0) + continue; + + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "%s: ", + check_altname[j].name); + (*check_altname[j].func)(ctx, &gn.val[i].u.otherName.value); + break; + } + if (j == sizeof(check_altname)/sizeof(check_altname[0])) { + hx509_oid_print(&gn.val[i].u.otherName.type_id, + validate_vprint, ctx); + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, " unknown"); + } + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "\n"); + break; + } + default: { + char *s; + ret = hx509_general_name_unparse(&gn.val[i], &s); + if (ret) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "ret = %d unparsing GeneralName\n", ret); + return 1; + } + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "%s\n", s); + free(s); + break; + } + } + } + + 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 && *b.cA ? "" : "NOT "); + if (b.pathLenConstraint) + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + "\tpathLenConstraint: %d\n", *b.pathLenConstraint); + + if (b.cA) { + if (*b.cA) { + if (!e->critical) + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Is a CA and not BasicConstraints CRITICAL\n"); + status->isca = 1; + } + else + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "cA is FALSE, not allowed to be\n"); + } + 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, 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); + hx509_general_name_unparse(&aia.val[i].accessLocation, &str); + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + "\n\tdirname: %s\n", str); + free(str); + } + free_AuthorityInfoAccessSyntax(&aia); + + return 0; +} + +/* + * + */ + +struct { + const char *name; + const heim_oid *(*oid)(void); + 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, &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, Null) }, + { ext(policyMappings, Null), M_N_C }, + { ext(authorityKeyIdentifier, authorityKeyIdentifier), M_N_C }, + { ext(policyConstraints, Null), D_C }, + { ext(extKeyUsage, Null), D_C }, + { ext(freshestCRL, Null), M_N_C }, + { ext(inhibitAnyPolicy, Null), M_C }, +#undef ext +#define ext(name, checkname) #name, &oid_id_pkix_pe_##name, check_##checkname + { ext(proxyCertInfo, proxyCertInfo), M_C }, + { ext(authorityInfoAccess, authorityInfoAccess), M_C }, +#undef ext + { "US Fed PKI - PIV Interim", oid_id_uspkicommon_piv_interim, + check_Null, D_C }, + { "Netscape cert comment", oid_id_netscape_cert_comment, + check_Null, D_C }, + { NULL } +}; + +/** + * 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 + */ + +int +hx509_validate_ctx_init(hx509_context context, hx509_validate_ctx *ctx) +{ + *ctx = malloc(sizeof(**ctx)); + if (*ctx == NULL) + return ENOMEM; + memset(*ctx, 0, sizeof(**ctx)); + 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 + */ + +void +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 + */ + +void +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 + */ + +void +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 + */ + +int +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) { + int 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 extention: %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 extentions\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, + c, + &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/crypto/heimdal/lib/hx509/ref/pkcs11.h b/crypto/heimdal/lib/hx509/ref/pkcs11.h new file mode 100644 index 0000000..2e6a1e3 --- /dev/null +++ b/crypto/heimdal/lib/hx509/ref/pkcs11.h @@ -0,0 +1,1357 @@ +/* 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 20 +#define CRYPTOKI_VERSION_REVISION 6 + + +/* 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 + +#define CK_SPEC + +#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 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) + + +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 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_VENDOR_DEFINED ((unsigned long) (1 << 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) (1 << 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_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_VENDOR_DEFINED ((unsigned long) (1 << 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) (1 << 31)) + + +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_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_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_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_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_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE | 0x600) +#define CKA_VENDOR_DEFINED ((unsigned long) (1 << 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_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_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_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_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_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_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_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_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_KEY_WRAP_LYNKS (0x400) +#define CKM_KEY_WRAP_SET_OAEP (0x401) +#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_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_DSA_PARAMETER_GEN (0x2000) +#define CKM_DH_PKCS_PARAMETER_GEN (0x2001) +#define CKM_X9_42_DH_PARAMETER_GEN (0x2002) +#define CKM_VENDOR_DEFINED ((unsigned long) (1 << 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_EXTENSION ((unsigned long) (1 << 31)) + + +/* 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_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_FUNCTION_REJECTED (0x200) +#define CKR_VENDOR_DEFINED ((unsigned long) (1 << 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_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_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/crypto/heimdal/lib/hx509/req.c b/crypto/heimdal/lib/hx509/req.c new file mode 100644 index 0000000..d7a85e1 --- /dev/null +++ b/crypto/heimdal/lib/hx509/req.c @@ -0,0 +1,325 @@ +/* + * 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> +RCSID("$Id: req.c 21344 2007-06-26 14:22:34Z lha $"); + +struct hx509_request_data { + hx509_name name; + SubjectPublicKeyInfo key; + ExtKeyUsage eku; + GeneralNames san; +}; + +/* + * + */ + +int +_hx509_request_init(hx509_context context, hx509_request *req) +{ + *req = calloc(1, sizeof(**req)); + if (*req == NULL) + return ENOMEM; + + return 0; +} + +void +_hx509_request_free(hx509_request *req) +{ + if ((*req)->name) + hx509_name_free(&(*req)->name); + free_SubjectPublicKeyInfo(&(*req)->key); + free_ExtKeyUsage(&(*req)->eku); + free_GeneralNames(&(*req)->san); + memset(*req, 0, sizeof(**req)); + free(*req); + *req = NULL; +} + +int +_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; +} + +int +_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); +} + +int +_hx509_request_set_SubjectPublicKeyInfo(hx509_context context, + hx509_request req, + const SubjectPublicKeyInfo *key) +{ + free_SubjectPublicKeyInfo(&req->key); + return copy_SubjectPublicKeyInfo(key, &req->key); +} + +int +_hx509_request_get_SubjectPublicKeyInfo(hx509_context context, + hx509_request req, + SubjectPublicKeyInfo *key) +{ + return copy_SubjectPublicKeyInfo(&req->key, key); +} + +int +_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; +} + +int +_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 = rk_UNCONST(hostname); + + return add_GeneralNames(&req->san, &name); +} + +int +_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.dNSName = rk_UNCONST(email); + + return add_GeneralNames(&req->san, &name); +} + + + +int +_hx509_request_to_pkcs10(hx509_context context, + const hx509_request req, + const hx509_private_key signer, + heim_octet_string *request) +{ + CertificationRequest r; + heim_octet_string data, os; + int ret; + size_t size; + + if (req->name == NULL) { + hx509_set_error_string(context, 0, EINVAL, + "PKCS10 needs to have a subject"); + return EINVAL; + } + + memset(&r, 0, sizeof(r)); + memset(request, 0, sizeof(*request)); + + r.certificationRequestInfo.version = pkcs10_v1; + + ret = copy_Name(&req->name->der_name, + &r.certificationRequestInfo.subject); + if (ret) + goto out; + ret = copy_SubjectPublicKeyInfo(&req->key, + &r.certificationRequestInfo.subjectPKInfo); + if (ret) + goto out; + r.certificationRequestInfo.attributes = + calloc(1, sizeof(*r.certificationRequestInfo.attributes)); + if (r.certificationRequestInfo.attributes == NULL) { + ret = ENOMEM; + goto out; + } + + ASN1_MALLOC_ENCODE(CertificationRequestInfo, data.data, data.length, + &r.certificationRequestInfo, &size, ret); + if (ret) + goto out; + if (data.length != size) + abort(); + + ret = _hx509_create_signature(context, + signer, + _hx509_crypto_default_sig_alg, + &data, + &r.signatureAlgorithm, + &os); + free(data.data); + if (ret) + goto out; + r.signature.data = os.data; + r.signature.length = os.length * 8; + + ASN1_MALLOC_ENCODE(CertificationRequest, data.data, data.length, + &r, &size, ret); + if (ret) + goto out; + if (data.length != size) + abort(); + + *request = data; + +out: + free_CertificationRequest(&r); + + return ret; +} + +int +_hx509_request_parse(hx509_context context, + const char *path, + hx509_request *req) +{ + CertificationRequest r; + CertificationRequestInfo *rinfo; + hx509_name subject; + size_t len, size; + void *p; + int ret; + + if (strncmp(path, "PKCS10:", 7) != 0) { + hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION, + "unsupport type in %s", path); + return HX509_UNSUPPORTED_OPERATION; + } + path += 7; + + /* XXX PEM request */ + + ret = _hx509_map_file(path, &p, &len, NULL); + if (ret) { + hx509_set_error_string(context, 0, ret, "Failed to map file %s", path); + return ret; + } + + ret = decode_CertificationRequest(p, len, &r, &size); + _hx509_unmap_file(p, len); + if (ret) { + hx509_set_error_string(context, 0, ret, "Failed to decode %s", path); + return ret; + } + + ret = _hx509_request_init(context, req); + if (ret) { + free_CertificationRequest(&r); + return ret; + } + + rinfo = &r.certificationRequestInfo; + + ret = _hx509_request_set_SubjectPublicKeyInfo(context, *req, + &rinfo->subjectPKInfo); + if (ret) { + free_CertificationRequest(&r); + _hx509_request_free(req); + return ret; + } + + ret = _hx509_name_from_Name(&rinfo->subject, &subject); + if (ret) { + free_CertificationRequest(&r); + _hx509_request_free(req); + return ret; + } + ret = _hx509_request_set_name(context, *req, subject); + hx509_name_free(&subject); + free_CertificationRequest(&r); + if (ret) { + _hx509_request_free(req); + return ret; + } + + return 0; +} + + +int +_hx509_request_print(hx509_context context, hx509_request req, FILE *f) +{ + int ret; + + 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); + } + + return 0; +} + diff --git a/crypto/heimdal/lib/hx509/revoke.c b/crypto/heimdal/lib/hx509/revoke.c new file mode 100644 index 0000000..cfde439 --- /dev/null +++ b/crypto/heimdal/lib/hx509/revoke.c @@ -0,0 +1,1525 @@ +/* + * 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 certifiates 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" +RCSID("$Id: revoke.c 22275 2007-12-11 11:02:11Z lha $"); + +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 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 + */ + +int +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_revoke_ctx +_hx509_revoke_ref(hx509_revoke_ctx ctx) +{ + if (ctx == NULL) + return NULL; + if (ctx->ref <= 0) + _hx509_abort("revoke ctx refcount <= 0"); + ctx->ref++; + if (ctx->ref == 0) + _hx509_abort("revoke ctx refcount == 0"); + 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 + */ + +void +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) + 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 OSCP signer is " + "doesn't have CA as signer certificate"); + goto out; + } + + ret = _hx509_verify_signature_bitstring(context, + p, + &s->signatureAlgorithm, + &s->tbsCertificate._save, + &s->signatureValue); + if (ret) { + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + "OSCP signer signature invalid"); + goto out; + } + + ret = hx509_cert_check_eku(context, signer, + oid_id_pkix_kp_OCSPSigning(), 0); + if (ret) + goto out; + } + + ret = _hx509_verify_signature_bitstring(context, + _hx509_get_cert(signer), + &ocsp->ocsp.signatureAlgorithm, + &ocsp->ocsp.tbsResponseData._save, + &ocsp->ocsp.signature); + if (ret) { + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + "OSCP 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, + 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 = _hx509_map_file(ocsp->path, &data, &length, &sb); + if (ret) + return ret; + + ret = parse_ocsp_basic(data, length, &basic); + _hx509_unmap_file(data, length); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to parse OCSP response"); + return ret; + } + + if (basic.certs) { + int 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; + + ret = hx509_cert_init(context, &basic.certs->val[i], &c); + if (ret) + 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 + */ + +int +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) { + hx509_set_error_string(context, HX509_ERROR_APPEND, ret, + "Failed to find certificate for CRL"); + return ret; + } + } + + ret = _hx509_verify_signature_bitstring(context, + _hx509_get_cert(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 revoke " + "status of CRL signer"); + goto out; + } + } + +out: + hx509_cert_free(signer); + + return ret; +} + +static int +load_crl(const char *path, time_t *t, CRLCertificateList *crl) +{ + size_t length, size; + struct stat sb; + void *data; + int ret; + + memset(crl, 0, sizeof(*crl)); + + ret = _hx509_map_file(path, &data, &length, &sb); + if (ret) + return ret; + + *t = sb.st_mtime; + + ret = decode_CRLCertificateList(data, length, crl, &size); + _hx509_unmap_file(data, length); + if (ret) + return ret; + + /* check signature is aligned */ + if (crl->signatureValue.length & 7) { + free_CRLCertificateList(crl); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + return 0; +} + +/** + * 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 + */ + +int +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, + "unsupport type in %s", path); + return HX509_UNSUPPORTED_OPERATION; + } + + + path += 5; + + for (i = 0; i < ctx->crls.len; i++) { + if (strcmp(ctx->crls.val[0].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(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 + */ + + +int +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; + + /* check if cert.issuer == crls.val[i].crl.issuer */ + ret = _hx509_name_cmp(&c->tbsCertificate.issuer, + &crl->crl.tbsCertList.issuer); + if (ret) + continue; + + ret = stat(crl->path, &sb); + if (ret == 0 && crl->last_modfied != sb.st_mtime) { + CRLCertificateList cl; + + ret = load_crl(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 revoke 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 +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 + */ + +int +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(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(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]; + strlcpy(s, ctime(&t)+ 4, sizeof(s)); + s[20] = 0; + return s; +} + +/** + * 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 + */ + +int +hx509_revoke_ocsp_print(hx509_context context, const char *path, FILE *out) +{ + struct revoke_ocsp ocsp; + int ret, i; + + 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; + } + + 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%d. status: %s\n", 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(context, ocsp.certs, hx509_ci_print_names, 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 + */ + +int +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, 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 + */ + +int +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 + */ + +int +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 + */ + +int +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 + */ + +void +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 +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 + */ + +int +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(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); + + ASN1_MALLOC_ENCODE(CRLCertificateList, os->data, os->length, + &c, &size, ret); + free_CRLCertificateList(&c); + 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"); + + return 0; + +out: + free_CRLCertificateList(&c); + return ret; +} diff --git a/crypto/heimdal/lib/hx509/softp11.c b/crypto/heimdal/lib/hx509/softp11.c new file mode 100644 index 0000000..86bb1d6 --- /dev/null +++ b/crypto/heimdal/lib/hx509/softp11.c @@ -0,0 +1,1740 @@ +/* + * 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" +#include "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) + + +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; + len = vsnprintf(str, size, fmt, ap); + va_end(ap); + if (len < 0 || len > size) + return; + while(len < size) + str[len++] = fillchar; +} + +#ifndef TEST_APP +#define printf error_use_st_logf +#endif + +#define VERIFY_SESSION_HANDLE(s, state) \ +{ \ + CK_RV ret; \ + ret = verify_session_handle(s, state); \ + if (ret != CKR_OK) { \ + /* return CKR_OK */; \ + } \ +} + +static CK_RV +verify_session_handle(CK_SESSION_HANDLE hSession, + struct session_state **state) +{ + int 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 = malloc(sizeof(*o)); + if (o == NULL) + return NULL; + memset(o, 0, sizeof(*o)); + o->attrs = NULL; + o->num_attributes = 0; + + for (i = 0; i < soft_token.object.num_objs; i++) { + if (soft_token.object.objs == 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; + + 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; + 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 +add_cert(hx509_context hxctx, void *ctx, hx509_cert cert) +{ + 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, "", 1); /* XXX */ + add_object_attribute(o, 0, CKA_END_DATE, "", 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; + 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, "", 1); /* XXX */ + add_object_attribute(o, 0, CKA_END_DATE, "", 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); + + 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; + asprintf(&str, "PASS:%s", pin); + + 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(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; + int anchor; + FILE *f; + CK_RV ret = CKR_OK; + CK_RV failed = CKR_OK; + + f = fopen(fn, "r"); + if (f == NULL) { + st_logf("can't open configuration file %s\n", fn); + return CKR_GENERAL_ERROR; + } + + while(fgets(buf, sizeof(buf), f) != NULL) { + buf[strcspn(buf, "\n")] = '\0'; + + anchor = 0; + + st_logf("line: %s\n", buf); + + p = buf; + while (isspace(*p)) + p++; + if (*p == '#') + continue; + while (isspace(*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 == 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; +} + +CK_RV +C_Initialize(CK_VOID_PTR a) +{ + CK_C_INITIALIZE_ARGS_PTR args = a; + CK_RV ret; + int i; + + st_logf("Initialize\n"); + + INIT_CONTEXT(); + + OpenSSL_add_all_algorithms(); + + srandom(getpid() ^ 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); + } + + { + char *fn = NULL, *home = NULL; + + if (getuid() == geteuid()) { + fn = getenv("SOFTPKCS11RC"); + if (fn) + fn = strdup(fn); + home = getenv("HOME"); + } + if (fn == NULL && home == NULL) { + struct passwd *pw = getpwuid(getuid()); + if(pw != NULL) + home = pw->pw_dir; + } + if (fn == NULL) { + if (home) + asprintf(&fn, "%s/.soft-token.rc", home); + else + fn = strdup("/etc/soft-token.rc"); + } + + soft_token.config_file = fn; + } + + /* + * 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) +{ + int 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[1] = 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) +{ + int 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) +{ + int 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) { + asprintf(&pin, "%.*s", (int)ulPinLen, pPin); + st_logf("type: %d password: %s\n", (int)userType, pin); + } + + /* + * 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 *dup, const CK_MECHANISM_PTR pMechanism) +{ + CK_MECHANISM_PTR p; + + p = malloc(sizeof(*p)); + if (p == NULL) + return CKR_DEVICE_MEMORY; + + if (*dup) + free(*dup); + *dup = 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; + uint 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, + _hx509_get_cert(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/crypto/heimdal/lib/hx509/test_ca.in b/crypto/heimdal/lib/hx509/test_ca.in new file mode 100644 index 0000000..5cc124d --- /dev/null +++ b/crypto/heimdal/lib/hx509/test_ca.in @@ -0,0 +1,424 @@ +#!/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: test_ca.in 21345 2007-06-26 14:22:57Z lha $ +# + +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 + +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" \ + --certificate="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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +exit 0 diff --git a/crypto/heimdal/lib/hx509/test_cert.in b/crypto/heimdal/lib/hx509/test_cert.in new file mode 100644 index 0000000..ed04bfa --- /dev/null +++ b/crypto/heimdal/lib/hx509/test_cert.in @@ -0,0 +1,69 @@ +#!/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 || 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 + + +exit 0 diff --git a/crypto/heimdal/lib/hx509/test_chain.in b/crypto/heimdal/lib/hx509/test_chain.in new file mode 100644 index 0000000..a99ae5e --- /dev/null +++ b/crypto/heimdal/lib/hx509/test_chain.in @@ -0,0 +1,242 @@ +#!/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: test_chain.in 21278 2007-06-25 04:54:43Z lha $ +# + +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 + +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/crypto/heimdal/lib/hx509/test_cms.in b/crypto/heimdal/lib/hx509/test_cms.in new file mode 100644 index 0000000..a89e810 --- /dev/null +++ b/crypto/heimdal/lib/hx509/test_cms.in @@ -0,0 +1,377 @@ +#!/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: test_cms.in 21311 2007-06-25 18:26:37Z lha $ +# + +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 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 (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 "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 "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 "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 "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 \ + "$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/crypto/heimdal/lib/hx509/test_crypto.in b/crypto/heimdal/lib/hx509/test_crypto.in new file mode 100644 index 0000000..31b5233 --- /dev/null +++ b/crypto/heimdal/lib/hx509/test_crypto.in @@ -0,0 +1,187 @@ +#!/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: test_crypto.in 20898 2007-06-04 23:07:46Z lha $ +# + +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 + +exit 0 diff --git a/crypto/heimdal/lib/hx509/test_java_pkcs11.in b/crypto/heimdal/lib/hx509/test_java_pkcs11.in new file mode 100644 index 0000000..35f61e6 --- /dev/null +++ b/crypto/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/crypto/heimdal/lib/hx509/test_name.c b/crypto/heimdal/lib/hx509/test_name.c new file mode 100644 index 0000000..2c6dd51 --- /dev/null +++ b/crypto/heimdal/lib/hx509/test_name.c @@ -0,0 +1,132 @@ +/* + * 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" +RCSID("$Id: test_name.c 19882 2007-01-13 01:02:57Z lha $"); + +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; + hx509_name n; + char *s; + int ret; + + hx509_env_init(context, &env); + 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; +} + +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"); + + hx509_context_free(&context); + + return ret; +} diff --git a/crypto/heimdal/lib/hx509/test_nist.in b/crypto/heimdal/lib/hx509/test_nist.in new file mode 100644 index 0000000..8306283 --- /dev/null +++ b/crypto/heimdal/lib/hx509/test_nist.in @@ -0,0 +1,116 @@ +#!/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: test_nist.in 22240 2007-12-08 22:55:03Z lha $ +# + +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 + +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 $args > /dev/null; then + if test "$verify" = "f"; then + echo "verify passed on fail: $id $cert" + exit 1 + fi + else + if test "$verify" = "p"; then + echo "verify failed on pass: $id $cert" + exit 1 + fi + fi + +done < $srcdir/data/nist-data + + +echo "done!" + +exit 0 diff --git a/crypto/heimdal/lib/hx509/test_nist2.in b/crypto/heimdal/lib/hx509/test_nist2.in new file mode 100644 index 0000000..6616129 --- /dev/null +++ b/crypto/heimdal/lib/hx509/test_nist2.in @@ -0,0 +1,118 @@ +#!/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: 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 + +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 + +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" +# args="$args crl:FILE:$nistdir/crls/TrustAnchorRootCRL.crl" + + for a in $nistdir/crls/*.crl; do + args="$args crl:FILE:$a" + done + + cmd="${hxtool} verify $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 grep "${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 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/crypto/heimdal/lib/hx509/test_nist_cert.in b/crypto/heimdal/lib/hx509/test_nist_cert.in new file mode 100644 index 0000000..2d2bbe1 --- /dev/null +++ b/crypto/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: test_nist_cert.in 21823 2007-08-03 15:13:37Z lha $ +# + +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/crypto/heimdal/lib/hx509/test_nist_pkcs12.in b/crypto/heimdal/lib/hx509/test_nist_pkcs12.in new file mode 100644 index 0000000..fe595f2 --- /dev/null +++ b/crypto/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: test_nist_pkcs12.in 22256 2007-12-09 06:04:02Z lha $ +# + +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/crypto/heimdal/lib/hx509/test_pkcs11.in b/crypto/heimdal/lib/hx509/test_pkcs11.in new file mode 100644 index 0000000..0a315bf --- /dev/null +++ b/crypto/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/crypto/heimdal/lib/hx509/test_query.in b/crypto/heimdal/lib/hx509/test_query.in new file mode 100644 index 0000000..01e0c31 --- /dev/null +++ b/crypto/heimdal/lib/hx509/test_query.in @@ -0,0 +1,146 @@ +#!/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: test_query.in 20782 2007-06-02 00:46:00Z lha $ +# + +srcdir="@srcdir@" +objdir="@objdir@" + +stat="--statistic-file=${objdir}/statfile" + +hxtool="${TESTS_ENVIRONMENT} ./hxtool ${stat}" + +echo "try printing" +${hxtool} print \ + --pass=PASS:foobar \ + PKCS12:$srcdir/data/test.p12 >/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 (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 + +exit 0 + diff --git a/crypto/heimdal/lib/hx509/test_req.in b/crypto/heimdal/lib/hx509/test_req.in new file mode 100644 index 0000000..2109ceb --- /dev/null +++ b/crypto/heimdal/lib/hx509/test_req.in @@ -0,0 +1,63 @@ +#!/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: test_req.in 21341 2007-06-26 14:20:56Z lha $ +# + +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 \ + 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" \ + --dnsname=nutcracker.it.su.se \ + --key=FILE:$srcdir/data/key.der \ + request.out || exit 1 diff --git a/crypto/heimdal/lib/hx509/test_soft_pkcs11.c b/crypto/heimdal/lib/hx509/test_soft_pkcs11.c new file mode 100644 index 0000000..e76f772 --- /dev/null +++ b/crypto/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 "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 (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/crypto/heimdal/lib/hx509/test_windows.in b/crypto/heimdal/lib/hx509/test_windows.in new file mode 100644 index 0000000..8614544 --- /dev/null +++ b/crypto/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: test_windows.in 21004 2007-06-08 01:53:10Z lha $ +# + +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/crypto/heimdal/lib/hx509/tst-crypto-available1 b/crypto/heimdal/lib/hx509/tst-crypto-available1 new file mode 100644 index 0000000..71fa741 --- /dev/null +++ b/crypto/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/crypto/heimdal/lib/hx509/tst-crypto-available2 b/crypto/heimdal/lib/hx509/tst-crypto-available2 new file mode 100644 index 0000000..b3f76e3 --- /dev/null +++ b/crypto/heimdal/lib/hx509/tst-crypto-available2 @@ -0,0 +1,4 @@ +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 diff --git a/crypto/heimdal/lib/hx509/tst-crypto-available3 b/crypto/heimdal/lib/hx509/tst-crypto-available3 new file mode 100644 index 0000000..0b1a855 --- /dev/null +++ b/crypto/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/crypto/heimdal/lib/hx509/tst-crypto-select b/crypto/heimdal/lib/hx509/tst-crypto-select new file mode 100644 index 0000000..399c883 --- /dev/null +++ b/crypto/heimdal/lib/hx509/tst-crypto-select @@ -0,0 +1 @@ +1.2.840.113549.1.1.11 diff --git a/crypto/heimdal/lib/hx509/tst-crypto-select1 b/crypto/heimdal/lib/hx509/tst-crypto-select1 new file mode 100644 index 0000000..eb0d095 --- /dev/null +++ b/crypto/heimdal/lib/hx509/tst-crypto-select1 @@ -0,0 +1 @@ +1.3.14.3.2.26 diff --git a/crypto/heimdal/lib/hx509/tst-crypto-select2 b/crypto/heimdal/lib/hx509/tst-crypto-select2 new file mode 100644 index 0000000..749a549 --- /dev/null +++ b/crypto/heimdal/lib/hx509/tst-crypto-select2 @@ -0,0 +1 @@ +1.2.840.113549.1.1.5 diff --git a/crypto/heimdal/lib/hx509/tst-crypto-select3 b/crypto/heimdal/lib/hx509/tst-crypto-select3 new file mode 100644 index 0000000..ba9f29f --- /dev/null +++ b/crypto/heimdal/lib/hx509/tst-crypto-select3 @@ -0,0 +1 @@ +1.2.840.113549.1.1.4 diff --git a/crypto/heimdal/lib/hx509/tst-crypto-select4 b/crypto/heimdal/lib/hx509/tst-crypto-select4 new file mode 100644 index 0000000..749a549 --- /dev/null +++ b/crypto/heimdal/lib/hx509/tst-crypto-select4 @@ -0,0 +1 @@ +1.2.840.113549.1.1.5 diff --git a/crypto/heimdal/lib/hx509/tst-crypto-select5 b/crypto/heimdal/lib/hx509/tst-crypto-select5 new file mode 100644 index 0000000..399c883 --- /dev/null +++ b/crypto/heimdal/lib/hx509/tst-crypto-select5 @@ -0,0 +1 @@ +1.2.840.113549.1.1.11 diff --git a/crypto/heimdal/lib/hx509/tst-crypto-select6 b/crypto/heimdal/lib/hx509/tst-crypto-select6 new file mode 100644 index 0000000..749a549 --- /dev/null +++ b/crypto/heimdal/lib/hx509/tst-crypto-select6 @@ -0,0 +1 @@ +1.2.840.113549.1.1.5 diff --git a/crypto/heimdal/lib/hx509/tst-crypto-select7 b/crypto/heimdal/lib/hx509/tst-crypto-select7 new file mode 100644 index 0000000..9b0ac64 --- /dev/null +++ b/crypto/heimdal/lib/hx509/tst-crypto-select7 @@ -0,0 +1 @@ +2.16.840.1.101.3.4.1.42 diff --git a/crypto/heimdal/lib/hx509/version-script.map b/crypto/heimdal/lib/hx509/version-script.map new file mode 100644 index 0000000..68ef73e --- /dev/null +++ b/crypto/heimdal/lib/hx509/version-script.map @@ -0,0 +1,227 @@ +# $Id$ + +HEIMDAL_X509_1.0 { + global: + initialize_hx_error_table_r; + hx509_bitstring_print; + hx509_ca_sign; + hx509_ca_sign_self; + hx509_ca_tbs_add_crl_dp_uri; + hx509_ca_tbs_add_eku; + 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_pkinit; + hx509_ca_tbs_add_san_rfc822name; + hx509_ca_tbs_free; + hx509_ca_tbs_init; + hx509_ca_tbs_set_ca; + hx509_ca_tbs_set_domaincontroller; + hx509_ca_tbs_set_notAfter; + hx509_ca_tbs_set_notAfter_lifetime; + hx509_ca_tbs_set_notBefore; + 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_subject_expand; + hx509_ca_tbs_template_units; + hx509_cert_binary; + hx509_cert_check_eku; + hx509_cert_cmp; + hx509_cert_find_subjectAltName_otherName; + hx509_cert_free; + hx509_cert_get_SPKI; + hx509_cert_attribute; + 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_serialnumber; + hx509_cert_get_subject; + hx509_cert_init; + hx509_cert_init_data; + hx509_cert_keyusage_print; + hx509_cert; + hx509_cert_ref; + hx509_cert_set_friendly_name; + hx509_certs_add; + hx509_certs_append; + hx509_certs_end_seq; + hx509_certs_find; + hx509_certs_free; + hx509_certs_info; + hx509_certs_init; + hx509_certs_iter; + 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_1; + hx509_cms_decrypt_encrypted; + hx509_cms_envelope_1; + hx509_cms_unenvelope; + hx509_cms_unwrap_ContentInfo; + hx509_cms_verify_signed; + 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_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_params; + hx509_crypto_set_random_key; + hx509_env_add; + 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_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_cmp; + hx509_name_copy; + hx509_name_expand; + hx509_name_free; + hx509_name_is_null_p; + hx509_name_normalize; + hx509_name_to_Name; + hx509_name_binary; + hx509_name_to_string; + hx509_ocsp_request; + hx509_ocsp_verify; + hx509_oid_print; + hx509_oid_sprint; + hx509_parse_name; + hx509_peer_info_alloc; + hx509_peer_info_free; + hx509_peer_info_set_cert; + hx509_peer_info_set_cms_algs; + hx509_print_stdout; + hx509_prompt_hidden; + hx509_query_alloc; + hx509_query_free; + hx509_query_match_cmp_func; + 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_verify; + hx509_set_error_string; + hx509_set_error_stringv; + hx509_signature_md2; + hx509_signature_md5; + hx509_signature_rsa; + hx509_signature_rsa_with_md2; + 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_pem_write; + hx509_pem_add_header; + hx509_pem_find_header; + hx509_pem_free_header; + hx509_xfree; + _hx509_write_file; + _hx509_map_file; + _hx509_map_file_os; + _hx509_unmap_file; + _hx509_unmap_file_os; + _hx509_certs_keys_free; + _hx509_certs_keys_get; + _hx509_request_init; + _hx509_request_add_dns_name; + _hx509_request_add_email; + _hx509_request_get_name; + _hx509_request_set_name; + _hx509_request_set_email; + _hx509_request_get_SubjectPublicKeyInfo; + _hx509_request_set_SubjectPublicKeyInfo; + _hx509_request_to_pkcs10; + _hx509_request_to_pkcs10; + _hx509_request_free; + _hx509_request_print; + _hx509_request_parse; + _hx509_private_key_ref; + _hx509_private_key_free; + _hx509_private_key2SPKI; + _hx509_generate_private_key_init; + _hx509_generate_private_key_is_ca; + _hx509_generate_private_key_bits; + _hx509_generate_private_key; + _hx509_generate_private_key_free; + _hx509_cert_assign_key; + _hx509_cert_private_key; + _hx509_name_from_Name; + # pkcs11 symbols + C_GetFunctionList; + local: + *; +}; + |