yubihsm-shell-2.7.1/0000755000175100017510000000000015133003464013713 5ustar runnerrunneryubihsm-shell-2.7.1/doc/0000755000175100017510000000000015133003406014454 5ustar runnerrunneryubihsm-shell-2.7.1/doc/API_Changes.adoc0000644000175100017510000003263415133003406017355 0ustar runnerrunner== 1.0.4 -> 2.0.0 === Definitions ==== Return Codes [options="header"] |======================= |1.0.4 | 2.0.0 | Numeric value |`YHR_MEMORY` | `YHR_MEMORY_ERROR` | `-1` |`YHR_NET_ERROR` | `YHR_CONNECTION_ERROR` | `-3` |`YHR_INVALID_PARAMS` | `YHR_INVALID_PARAMETERS` | `-5` |`YHR_AUTH_SESSION_ERROR` | `YHR_SESSION_AUTHENTICATION_FAILED` | `-9` |`YHR_DEVICE_INV_COMMAND` | `YHR_DEVICE_INVALID_COMMAND` | `-12` |`YHR_DEVICE_INV_DATA` | `YHR_DEVICE_INVALID_DATA` | `-13` |`YHR_DEVICE_INV_SESSION` | `YHR_DEVICE_INVALID_SESSION` | `-14` |`YHR_DEVICE_AUTH_FAIL` | `YHR_DEVICE_AUTHENTICATION_FAILED` | `-15` |`YHR_DEVICE_INV_PERMISSION` | `YHR_DEVICE_INSUFFICIENT_PERMISSIONS` | `-20` |`YHR_DEVICE_OBJ_NOT_FOUND` | `YHR_DEVICE_OBJECT_NOT_FOUND` | `-22` |`YHR_DEVICE_ID_ILLEGAL` | `YHR_DEVICE_INVALID_ID` | `-23` |`YHR_DEVICE_CMD_UNEXECUTED` | `YHR_DEVICE_COMMAND_UNEXECUTED` | `-26` | - | `YHR_DEVICE_SSH_CA_CONSTRAINT_VIOLATION` | `-30` |======================= ==== Object Types [options="header"] |======================= |1.0.4 | 2.0.0 | Hex value |`YH_AUTHKEY` | `YH_AUTHENTICATION_KEY` | `0x02` |`YH_ASYMMETRIC` | `YH_ASYMMETRIC_KEY` | `0x03` |`YH_WRAPKEY` | `YH_WRAP_KEY` | `0x04` |`YH_HMACKEY` | `YH_HMAC_KEY` | `0x05` |`YH_PUBLIC` | `YH_PUBLIC_KEY` | `0x83` |======================= ==== Algorithms [options="header"] |======================= |1.0.4 | 2.0.0 | Numeric value |`YH_ALGO_OPAQUE_X509_CERT` | `YH_ALGO_OPAQUE_X509_CERTIFICATE` | `31` |`YH_ALGO_TEMPL_SSH` | `YH_ALGO_TEMPLATE_SSH` | `36` |`YH_ALGO_YUBICO_OTP_AES128` | `YH_ALGO_AES128_YUBICO_OTP` | `37` |`YH_ALGO_YUBICO_AES_AUTH` | `YH_ALGO_AES128_YUBICO_AUTHENTICATION` | `38` |`YH_ALGO_YUBICO_OTP_AES192` | `YH_ALGO_AES192_YUBICO_OTP` | `39` |`YH_ALGO_YUBICO_OTP_AES256` | `YH_ALGO_AES256_YUBICO_OTP` | `40` |======================= ==== Commands [options="header"] |======================= |1.0.4 | 2.0.0 | Hex value |`YHC_CREATE_SES` | `YHC_CREATE_SESSION` | `0x03` |`YHC_AUTH_SES` | `YHC_AUTHENTICATE_SESSION` | `0x04` |`YHC_SES_MSG` | `YHC_SESSION_MESSAGE` | `0x05` |`YHC_RESET` | `YHC_RESET_DEVICE` | `0x08` |`YHC_CLOSE_SES` | `YHC_CLOSE_SESSION` | `0x40` |`YHC_STATS` | `YHC_GET_STORAGE_INFO` | `0x41` |`YHC_PUT_AUTHKEY` | `YHC_PUT_AUTHENTICATION_KEY` | `0x44` |`YHC_GEN_ASYMMETRIC_KEY` | `YHC_GENERATE_ASYMMETRIC_KEY` | `0x46` |`YHC_SIGN_DATA_PKCS1` | `YHC_SIGN_PKCS1` | `0x47` |`YHC_LIST` | `YHC_LIST_OBJECTS` | `0x48` |`YHC_GET_LOGS` | `YHC_GET_LOG_ENTRIES` | `0x4d` |`YHC_PUT_OPTION` | `YHC_SET_OPTION` | `0x4f` |`YHC_HMAC_DATA` | `YHC_SIGN_HMAC` | `0x53` |`YHC_GET_PUBKEY` | `YHC_GET_PUBLIC_KEY` | `0x54` |`YHC_SIGN_DATA_PSS` | `YHC_SIGN_PSS` | `0x55` |`YHC_SIGN_DATA_ECDSA` | `YHC_SIGN_ECDSA` | `0x56` |`YHC_DECRYPT_ECDH` | `YHC_DERIVE_ECDH` | `0x57` |`YHC_SSH_CERTIFY` | `YHC_SIGN_SSH_CERTIFICATE` | `0x5d` |`YHC_OTP_DECRYPT` | `YHC_DECRYPT_OTP` | `0x60` |`YHC_OTP_AEAD_CREATE` | `YHC_CREATE_OTP_AEAD` | `0x61` |`YHC_OTP_AEAD_RANDOM` | `YHC_RANDOMIZE_OTP_AEAD` | `0x62` |`YHC_OTP_AEAD_REWRAP` | `YHC_REWRAP_OTP_AEAD` | `0x63` |`YHC_ATTEST_ASYMMETRIC` | `YHC_SIGN_ATTESTATION_CERTIFICATE` | `0x64` |`YHC_SIGN_DATA_EDDSA` | `YHC_SIGN_EDDSA` | `0x6a` |`YHC_BLINK` | `YHC_BLINK_DEVICE` | `0x6b` | - | `YHC_CHANGE_AUTHENTICATION_KEY` | `0x6c` |======================= === Object Types [options="header"] |======================= |1.0.4 | 2.0.0 | Hex value |`authkey` | `authentication-key` | `0x02 |`asymmetric` | `asymmetric-key` | `0x03 |`hmackey` | `hmac-key` | `0x05 |`otpaeadkey` | `otp-aead-key` | `0x07 |`wrapkey` | `wrap-key` | `0x04` |======================= === Capabilities [options="header"] |======================= |1.0.4 | 2.0.0 | Hex value |`asymmetric_decrypt_ecdh` | `derive-ecdh` | `0x0b` |`asymmetric_decrypt_oaep` | `decrypt-oaep` | `0x0a` |`asymmetric_decrypt_pkcs` | `decrypt-pkcs` | `0x09` |`asymmetric_gen` | `generate-asymmetric-key` | `0x04` |`asymmetric_sign_ecdsa` | `sign-ecdsa` | `0x07` |`asymmetric_sign_eddsa` | `sign-eddsa` | `0x08` |`asymmetric_sign_pkcs` | `sign-pkcs` | `0x05` |`asymmetric_sign_pss` | `sign-pss` | `0x06` |`attest` | `sign-attestation-certificate` | `0x22` |`audit` | `get-log-entries` | `0x18` |`export_ under_wrap` | `exportable-under-wrap` | `0x10` |`export_wrapped` | `export-wrapped` | `0x0c` |`delete_asymmetric` | `delete-asymmetric-key` | `0x29` |`delete_authkey` | `delete-authentication-key` | `0x28` |`delete_hmackey` | `delete-hmac-key` | `0x2b` |`delete_opaque` | `delete-opaque` | `0x27` |`delete_otp_aead_key` | `delete-otp-aead-key` | `0x2d` |`delete_template` | `delete-template` | `0x2c` |`delete_wrapkey` | `delete-wrap-key` | `0x2a` |`generate_otp_aead_key` | `generate-otp-aead-key` | `0x24` |`generate_wrapkey` | `generate-wrap-key` | `0x0f` |`get_opaque` | `get-opaque` | `0x00` |`get_option` | `get-option` | `0x12` |`get_randomness` | `get-pseudo-random` | `0x13` |`get_template` | `get-template` | `0x1a` |`hmackey_generate` | `generate-hmac-key` | `0x15` |`hmac_data` | `sign-hmac` | `0x16` |`hmac_verify` | `verify-hmac` | `0x17` |`import_wrapped` | `import-wrapped` | `0x0d` |`otp_aead_create` | `create-otp-aead` | `0x1e` |`otp_aead_random` | `randomize-otp-aead` | `0x1f` |`otp_aead_rewrap_from` | `rewrap-from-otp-aead-key` | `0x20` |`otp_aead_rewrap_to` | `rewrap-to-otp-aead-key` | `0x21` |`otp_decrypt` | `decrypt-otp` | `0x1d` |`put_asymmetric` | `put-asymmetric-key` | `0x03` |`put_authkey` | `put-authentication-key` | `0x02` |`put_hmackey` | `put-mac-key` | `0x14` |`put_opaque` | `put-opaque` | `0x01` |`put_option` | `set-option` | `0x11` |`put_otp_aead_key` | `put-otp-aead-key` | `0x23` |`put_template` | `put-template` | `0x1b` |`put_wrapkey` | `put-wrap-key` | `0x0e` |`reset` | `reset-device` | `0x1c` |`ssh_certify` | `sign-ssh-certificate` | `0x19` |`unwrap_data` | `unwrap-data` | `0x26` |`wrap_data` | `wrap-data` | `0x25` | - | `change-authentication-key` | `0x2e` |======================= === Algorithms [options="header"] |======================= |1.0.4 | 2.0.0 | Numeric value |`yubico-aes-auth` | `aes128-yubico-authentication` | `38` |`yubico-otp-aes128` | `aes128-yubico-otp` | `37` |`yubico-otp-aes192` | `aes192-yubico-otp` | `39` |`yubico-otp-aes256` | `aes256-yubico-otp` | `40` |`opaque` | `opaque-data` | `30` |`x509-cert` | `opaque-x509-certificate` | `31` |======================= === Device Options [options="header"] |======================= |1.0.4 | 2.0.0 | Numeric value |`command_audit` | `command-audit` | `3` |`force_audit` | `force-audit` | `1` |======================= === Function Calls [options="header"] |======================= |1.0.4 | 2.0.0 |`yh_rc yh_set_verbosity(uint8_t verbosity)` | `yh_rc yh_set_verbosity(yh_connector *connector, uint8_t verbosity)` |`void yh_set_debug_output(FILE *output)` | `void yh_set_debug_output(yh_connector *connector, FILE *output)` |`yh_rc yh_connect_all(yh_connector **connectors, size_t *n_connectors, int timeout), yh_rc yh_connect_best(yh_connector **connectors, size_t n_connectors, int *idx` | `yh_rc yh_connect(yh_connector *connector, int timeout)` |`yh_rc yh_create_session_derived(yh_connector *connector, uint16_t auth_keyset_id, const uint8_t *password, size_t password_len, bool recreate_session, uint8_t *context, size_t context_len, yh_session **session)` | `yh_rc yh_create_session_derived(yh_connector *connector, uint16_t authkey_id, const uint8_t *password, size_t password_len, bool recreate_session, yh_session **session)` |`yh_rc yh_create_session(yh_connector *connector, uint16_t auth_keyset_id, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len, bool recreate_session, uint8_t *context, size_t context_len, yh_session **session)` | `yh_rc yh_create_session(yh_connector *connector, uint16_t authkey_id, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len, bool recreate_session, yh_session **session)` |`yh_rc yh_begin_create_session_ext(yh_connector *connector, uint16_t auth_keyset_id, uint8_t *context, size_t context_len, uint8_t *card_cryptogram, size_t card_cryptogram_len, yh_session **session)` | `yh_rc yh_begin_create_session_ext(yh_connector *connector, uint16_t authkey_id, uint8_t **context, uint8_t *card_cryptogram, size_t card_cryptogram_len, yh_session **session)` |`yh_rc yh_finish_create_session_ext(yh_connector *connector, yh_session *session, const uint8_t *key_senc, size_t key_senc_len, const uint8_t *key_smac, size_t key_smac_len, const uint8_t *key_srmac, size_t key_srmac_len, uint8_t *context, size_t context_len, uint8_t *card_cryptogram, size_t card_cryptogram_len)` | `yh_rc yh_finish_create_session_ext(yh_connector *connector, yh_session *session, const uint8_t *key_senc, size_t key_senc_len, const uint8_t *key_smac, size_t key_smac_len, const uint8_t *key_srmac, size_t key_srmac_len, uint8_t *card_cryptogram, size_t card_cryptogram_len)` |`yh_rc yh_authenticate_session(yh_session *session, uint8_t *context, size_t context_len)` | `yh_rc yh_authenticate_session(yh_session *session)` |`yh_rc yh_util_get_pubkey()` | `yh_rc yh_util_get_public_key()` |`yh_rc yh_util_hmac()` | `yh_rc yh_util_sign_hmac()` |`yh_rc yh_util_get_random()` | `yh_rc yh_util_get_pseudo_random()` |`yh_rc yh_util_import_key_rsa()` | `yh_rc yh_util_import_rsa_key()` |`yh_rc yh_util_import_key_ec()` | `yh_rc yh_util_import_ec_key()` |`yh_rc yh_util_import_key_ed()` | `yh_rc yh_util_import_ed_key()` |`yh_rc yh_util_import_key_hmac()` | `yh_rc yh_util_import_hmac_key()` |`yh_rc yh_util_generate_key_rsa()` | `yh_rc yh_util_generate_rsa_key()` |`yh_rc yh_util_generate_key_ec()` | `yh_rc yh_util_generate_ec_key()` |`yh_rc yh_util_generate_key_ed()` | `yh_rc yh_util_generate_ed_key()` |`yh_rc yh_util_hmac_verify()` | `yh_rc yh_util_verify_hmac()` |`yh_rc yh_util_generate_key_hmac()` | `yh_rc yh_util_generate_hmac_key()` |`yh_rc yh_util_decrypt_ecdh()` | `yh_rc yh_util_derive_ecdh()` |`yh_rc yh_util_import_key_wrap()` | `yh_rc yh_util_import_wrap_key()` |`yh_rc yh_util_generate_key_wrap()` | `yh_rc yh_util_generate_wrap_key()` |`yh_rc yh_util_get_logs()` | `yh_rc yh_util_get_log_entries()` |`yh_rc yh_util_ssh_certify()` | `yh_rc yh_util_sign_ssh_certificate()` |`yh_rc yh_util_import_authkey()` | `yh_rc yh_util_import_authentication_key_derived()` | - | `yh_rc yh_util_import_authentication_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, const yh_capabilities *delegated_capabilities, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len)` | - | `yh_rc yh_util_change_authentication_key(yh_session *session, uint16_t *key_id, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len)` | - | `yh_rc yh_util_change_authentication_key_derived(yh_session *session, uint16_t *key_id, const uint8_t *password, size_t password_len)` |`yh_rc yh_util_otp_aead_create()` | `yh_rc yh_util_create_otp_aead()` |`yh_rc yh_util_otp_aead_random()` | `yh_rc yh_util_randomize_otp_aead()` |`yh_rc yh_util_otp_decrypt()` | `yh_rc yh_util_decrypt_otp()` |`yh_rc yh_util_put_otp_aead_key()` | `yh_rc yh_util_import_otp_aead_key()` |`yh_rc yh_util_attest_asymmetric()` | `yh_rc yh_util_sign_attestation_certificate()` |`yh_rc yh_util_put_option()` | `yh_rc yh_util_set_option()` |`yh_rc yh_util_get_storage_stats()` | `yh_rc yh_util_get_storage_info()` |`yh_rc yh_util_blink()` | `yh_rc yh_util_blink_device()` |`yh_rc yh_util_reset()` | `yh_rc yh_util_reset_device()` |`yh_rc yh_capabilities_to_num()` | `yh_rc yh_string_to_capabilities()` |`yh_rc yh_num_to_capabilities()` | `yh_rc yh_capabilities_to_strings()` |`yh_rc yh_parse_domains()` | `yh_rc yh_string_to_domains()` |======================= yubihsm-shell-2.7.1/examples/0000755000175100017510000000000015133003406015525 5ustar runnerrunneryubihsm-shell-2.7.1/examples/ed25519_pvtkey.pem0000644000175100017510000000016715133003406020634 0ustar runnerrunner-----BEGIN PRIVATE KEY----- MC4CAQAwBQYDK2VwBCIEIEzNCJso/5banbbDRuwRTg9bijGfNaumJNqM9u1PuKb7 -----END PRIVATE KEY----- yubihsm-shell-2.7.1/examples/generate_ec.c0000644000175100017510000001126515133003406020137 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include #include #include #include #include #include #include "util.h" #include const char *key_label = "label"; const uint8_t password[] = "password"; const uint8_t data[] = "sudo make me a sandwich"; int main(void) { yh_connector *connector = NULL; yh_session *session = NULL; yh_rc yrc = YHR_GENERIC_ERROR; uint16_t authkey = 1; const char *connector_url; connector_url = getenv("DEFAULT_CONNECTOR_URL"); if (connector_url == NULL) { connector_url = DEFAULT_CONNECTOR_URL; } yrc = yh_init(); assert(yrc == YHR_SUCCESS); yrc = yh_init_connector(connector_url, &connector); assert(yrc == YHR_SUCCESS); yrc = yh_connect(connector, 0); assert(yrc == YHR_SUCCESS); yrc = yh_create_session_derived(connector, authkey, password, sizeof(password) - 1, false, &session); assert(yrc == YHR_SUCCESS); uint8_t session_id; yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d\n", session_id); yh_capabilities capabilities = {{0}}; yrc = yh_string_to_capabilities("sign-ecdsa", &capabilities); assert(yrc == YHR_SUCCESS); uint16_t domain_five = 0; yrc = yh_string_to_domains("5", &domain_five); assert(yrc == YHR_SUCCESS); uint16_t key_id = 0; // ID 0 lets the device generate an ID yrc = yh_util_generate_ec_key(session, &key_id, key_label, domain_five, &capabilities, YH_ALGO_EC_P256); assert(yrc == YHR_SUCCESS); printf("Generated key with ID %04x\n", key_id); printf("Data to sign (%zu bytes) is: %s\n", sizeof(data) - 1, data); EVP_MD_CTX *mdctx = NULL; uint8_t hashed_data[32]; unsigned int hashed_data_len; mdctx = EVP_MD_CTX_create(); assert(mdctx != NULL); EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL); EVP_DigestUpdate(mdctx, data, sizeof(data) - 1); EVP_DigestFinal_ex(mdctx, hashed_data, &hashed_data_len); EVP_MD_CTX_destroy(mdctx); printf("Hash of data (%d bytes) is:", EVP_MD_size(EVP_sha256())); for (unsigned int i = 0; i < hashed_data_len; i++) { printf(" %02x", hashed_data[i]); } printf("\n"); uint8_t signature[128]; size_t signature_len = sizeof(signature); yrc = yh_util_sign_ecdsa(session, key_id, hashed_data, hashed_data_len, signature, &signature_len); assert(yrc == YHR_SUCCESS); printf("Signature (%zu bytes) is:", signature_len); for (unsigned int i = 0; i < signature_len; i++) { printf(" %02x", signature[i]); } printf("\n"); uint8_t public_key[512]; size_t public_key_len = sizeof(public_key); yrc = yh_util_get_public_key(session, key_id, public_key, &public_key_len, NULL); assert(yrc == YHR_SUCCESS); printf("Public key (%zu bytes) is:", public_key_len); for (unsigned int i = 0; i < public_key_len; i++) { printf(" %02x", public_key[i]); } printf("\n"); EC_KEY *eckey = EC_KEY_new(); int nid = algo2nid(YH_ALGO_EC_P256); EC_POINT *point; EC_GROUP *group = EC_GROUP_new_by_curve_name(nid); assert(group != NULL); EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); EC_KEY_set_group(eckey, group); point = EC_POINT_new(group); memmove(public_key + 1, public_key, public_key_len); public_key[0] = 0x04; // hack to make it a valid ec pubkey.. public_key_len++; EC_POINT_oct2point(group, point, public_key, public_key_len, NULL); EC_KEY_set_public_key(eckey, point); if (ECDSA_verify(0, hashed_data, hashed_data_len, signature, signature_len, eckey) == 1) { printf("Signature successfully verified\n"); } else { printf("Unable to verify signature\n"); } EC_POINT_free(point); EC_KEY_free(eckey); EC_GROUP_free(group); yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yh_disconnect(connector); assert(yrc == YHR_SUCCESS); yrc = yh_exit(); assert(yrc == YHR_SUCCESS); return 0; } yubihsm-shell-2.7.1/examples/ssh_req.dat0000644000175100017510000000207315133003406017665 0ustar runnerrunner[*q Pa[A|gAuNAO7.G11ioZfd) {h^ IنѦ]pZo_*)^2A0X=IZI2G3K  7fhüۄk 4B\S]`˄/؆>J?'uW1*2mqBJĐ|eK$F?$ ZH*+oWhXEssh-rsa-cert-v01@openssh.com 4R,OYKSP5qcd*V@[o3]9UxAQ #include #include #include #include const uint8_t password[] = "password"; const uint8_t data[] = "sudo make me a sandwich"; int main(void) { yh_connector *connector = NULL; yh_rc yrc = YHR_GENERIC_ERROR; const char *connector_url; connector_url = getenv("DEFAULT_CONNECTOR_URL"); if (connector_url == NULL) { connector_url = DEFAULT_CONNECTOR_URL; } yrc = yh_init(); if (yrc != YHR_SUCCESS) { fprintf(stderr, "unable to initialize yubihsm: %s\n", yh_strerror(yrc)); exit(EXIT_FAILURE); } yrc = yh_init_connector(connector_url, &connector); assert(yrc == YHR_SUCCESS); yrc = yh_connect(connector, 0); assert(yrc == YHR_SUCCESS); char *received_url; yrc = yh_get_connector_address(connector, &received_url); assert(yrc == YHR_SUCCESS); yh_set_verbosity(connector, YH_VERB_ALL); printf("Send a plain (unencrypted, unauthenticated) echo command\n"); uint16_t data_len = sizeof(data) - 1; uint8_t response[sizeof(data)] = {0}; size_t response_len = sizeof(response); yh_cmd response_cmd; yrc = yh_send_plain_msg(connector, YHC_ECHO, data, data_len, &response_cmd, response, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to send ECHO command: %s\n", yh_strerror(yrc)); exit(EXIT_FAILURE); } printf("Response (%zu bytes): \"%s\"\n", response_len, response); yh_session *session = NULL; uint16_t authkey = 1; yrc = yh_create_session_derived(connector, authkey, password, sizeof(password) - 1, false, &session); assert(yrc == YHR_SUCCESS); uint8_t session_id; yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d\n", session_id); printf("Send a secure echo command\n"); uint8_t response2[sizeof(data)] = {0}; size_t response2_len = sizeof(response); yh_cmd response2_cmd; yrc = yh_send_secure_msg(session, YHC_ECHO, data, data_len, &response2_cmd, response2, &response2_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to send ECHO command: %s\n", yh_strerror(yrc)); exit(EXIT_FAILURE); } printf("Response (%zu bytes): \"%s\"\n", response_len, response); assert(response_len == response2_len); assert(memcmp(response, response2, response_len) == 0); yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yh_disconnect(connector); assert(yrc == YHR_SUCCESS); yrc = yh_exit(); assert(yrc == YHR_SUCCESS); return 0; } yubihsm-shell-2.7.1/examples/rsa2048_pvtkey.pem0000644000175100017510000000321315133003406020734 0ustar runnerrunner-----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEA1LILtPHUKTGvzNKpNHCSmRfE54NoabtPtV/SqAI/6VFT1PIf dLBUsBL19g4yAfnyOSTo5o8CYl6LzfdPgkyESXKzOYCKuBDEn14yQ/F1vzzydl5G a65dESVCFKUELu9IJwX1hjXpHLkwb9Wj8Z4h/Uikn6Xh3C6GvVOIJZGb9Kjcz+Mo Kx9IFAFAIWDV88DKUG9EontXYq4p2Vk6/XvAW63eQPWjUWeOSUiQp8UWtWA3SMZ9 GwxUh9ZRyd4gw1kqcrqMzwbJyEtmjBbYNnIGPYDCkr4YQJIoGPwNq6hh2HGa1J+M EYYZWVbl2GOW1FVMn75q45tnaCaWOlT0H7Om/wIDAQABAoIBAByVHJuhT9iFU9Gb kZ95bUnjdtOBxjtHL6v5B48KVlpdUn2wV+fPdmH++kyplbDMTO++9QleuHxNpk30 aRvieniAUHNuwbWAk1uzRd/5h9A+OXsMqjv4P4t5TUsG7ev8vd54n4j8n6n7fPXa aOCkVn76Dx1hJlv3aKXynr4ltiaHeABXz2ph5f7wHsC9cEqXjr4Tt+sXu9tURKMq hGNNYFgJPIsa0q07dqClJtNxS0hCkCp4gEFjsCVLFPzxEP+TU8OND7eNgXqQ9TYG zQGNEVN2Dmk/HFatTRnKY2wqlYjfFXhUsubVSPm0krIU04JeBgqo/B7u20G3wwW/ EWhA8skCgYEA73gkpHxKnykzJBx3jbPNgcegBJA2cqv7IonOO+KG1nqccnOzzYZX DFrEqemVuESPUSz1dzvilKkb2Fz+t8PFg9Qq4nV2Oa7h5TYp05T6dyuwrcmoPiIM 9kT7YGohaucf9EqRIYkjMbefWn9reiXKOztemD8Nq40GqT96zWdll+0CgYEA42DC vHnNS3ChPN6ueiiGrSYNiu0o35/+Zv0/YAXF69gC118qtBof8lVr74/vSE3SqNyh /8y8WhM/TlErZSSKoUZCIkQE3LhIsbR0Nh95RwY0It/jbnVTwb11/PkILfvaQlwQ 8DM2WXYg39QdPlYw1GNTvKuAYtzeROUqOoF5BRsCgYEA3qDTcBgdR9sFsIzGmPaQ GBd+rL9l3zYERBfZo9L1iHB1AfKPNoOuac35B/4hMy6KDu29Rxxlic+uE3hhVnar KeQV+nM5dmcfm/i+6fWW5TO5DdhskVcWtd1r1jbU2o4FJxgr1QGpto7/lyLeyLBZ UrffOatlChgSGUbq5As8aAECgYAogmivY5PryNkxGwtCwE2eM5VeFvqdPMf6WUwd M2obppR7An19MNpYNlfQing7DYJmi0hhZnx4H827ikKM9oGsUfQeXrfvCvYIkvnR WrIksTpArFq8pzKQ5cxLkaKfbqtn/zcVVEpujdk1h3jeTkTM0hVtG7D37Bm9dIad fcut2QKBgGwhl9lil+kDVkmWajQGHzxrct1hWlcn8hsXcO6bu8TGSYTjeT0XQUog OjdB5pTbPXncE/3ExaMttiBV8eLkhW+HRXq+IxyWPG3ROu5N1tTxBtV7X5tkzY9m V5rUvEN+bLOUGLGA4qd66j5DC0QwP1gaAHlpnMoipNvgXmEcriSu -----END RSA PRIVATE KEY----- yubihsm-shell-2.7.1/examples/change_authkey.c0000644000175100017510000001157615133003406020662 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include #include #include #include const char *key_label = "label"; const uint8_t password1[] = "password"; const uint8_t password2[] = "letmein!"; const uint8_t password3[] = "PASSWORD"; int main(void) { yh_connector *connector = NULL; yh_session *session = NULL; yh_rc yrc = YHR_GENERIC_ERROR; uint16_t authkey = 1; const char *connector_url; connector_url = getenv("DEFAULT_CONNECTOR_URL"); if (connector_url == NULL) { connector_url = DEFAULT_CONNECTOR_URL; } yrc = yh_init(); assert(yrc == YHR_SUCCESS); yrc = yh_init_connector(connector_url, &connector); assert(yrc == YHR_SUCCESS); yrc = yh_connect(connector, 0); assert(yrc == YHR_SUCCESS); yrc = yh_create_session_derived(connector, authkey, password1, sizeof(password1) - 1, false, &session); assert(yrc == YHR_SUCCESS); uint8_t session_id; yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d using Authentication Key " "%04x\n", session_id, authkey); yh_capabilities capabilities = {{0}}; yrc = yh_string_to_capabilities("change-authentication-key", &capabilities); assert(yrc == YHR_SUCCESS); uint16_t domain_five = 0; yrc = yh_string_to_domains("5", &domain_five); assert(yrc == YHR_SUCCESS); uint16_t key_id = 0; // ID 0 lets the device generate an ID yrc = yh_util_import_authentication_key_derived(session, &key_id, key_label, domain_five, &capabilities, &capabilities, password2, sizeof(password2)); assert(yrc == YHR_SUCCESS); printf("Imported Authentication Key with ID %04x and password \"%s\"\n", key_id, password2); yrc = yh_util_change_authentication_key_derived(session, &key_id, password3, sizeof(password3)); assert(yrc == YHR_DEVICE_INVALID_ID); printf("Unable to change Authentication Key with ID %04x from this session\n", key_id); yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); printf("Closed session %02d\n", session_id); yrc = yh_create_session_derived(connector, key_id, password2, sizeof(password2) - 1, false, &session); assert(yrc == YHR_SUCCESS); yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d using Authentication Key " "%04x\n", session_id, key_id); yrc = yh_util_change_authentication_key_derived(session, &key_id, password3, sizeof(password3)); assert(yrc == YHR_SUCCESS); printf("Successfully changed Authentication Key with ID %04x to password " "\"%s\"\n", key_id, password3); yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); printf("Closed session %02d\n", session_id); yrc = yh_create_session_derived(connector, key_id, password2, sizeof(password2) - 1, false, &session); assert(yrc == YHR_DEVICE_AUTHENTICATION_FAILED); printf("Unable to open session with Authentication Key %04x and password " "\"%s\"\n", key_id, password2); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yrc = yh_create_session_derived(connector, key_id, password3, sizeof(password3) - 1, false, &session); assert(yrc == YHR_SUCCESS); yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d using Authentcation Key %04x " "and password \"%s\"\n", session_id, key_id, password3); yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yh_disconnect(connector); assert(yrc == YHR_SUCCESS); yrc = yh_exit(); assert(yrc == YHR_SUCCESS); return 0; } yubihsm-shell-2.7.1/examples/wrap.c0000644000175100017510000004753115133003406016654 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include #include #include #include #include #include #include #include "util.h" #include "openssl-compat.h" const char *key_label = "label"; const uint8_t password[] = "password"; int main(void) { yh_connector *connector = NULL; yh_session *session = NULL; yh_rc yrc = YHR_GENERIC_ERROR; uint16_t authkey = 1; const char *connector_url; connector_url = getenv("DEFAULT_CONNECTOR_URL"); if (connector_url == NULL) { connector_url = DEFAULT_CONNECTOR_URL; } yrc = yh_init(); assert(yrc == YHR_SUCCESS); yrc = yh_init_connector(connector_url, &connector); assert(yrc == YHR_SUCCESS); yrc = yh_connect(connector, 0); assert(yrc == YHR_SUCCESS); yrc = yh_create_session_derived(connector, authkey, password, sizeof(password) - 1, false, &session); assert(yrc == YHR_SUCCESS); uint8_t session_id; yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d\n", session_id); yh_capabilities capabilities = {{0}}; yrc = yh_string_to_capabilities("export-wrapped:import-wrapped", &capabilities); assert(yrc == YHR_SUCCESS); yh_capabilities delegated_capabilities = {{0}}; yrc = yh_string_to_capabilities("sign-ecdsa:sign-eddsa:sign-pkcs:sign-pss:exportable-under-wrap", &delegated_capabilities); // delegated // capabilities has // to match the // capabilities of // the object we // want to export assert(yrc == YHR_SUCCESS); uint16_t domain_five = 0; yrc = yh_string_to_domains("5", &domain_five); assert(yrc == YHR_SUCCESS); const char data[] = "This is the data to sign"; uint8_t hashed_data[32]; unsigned int hashed_data_len = sizeof(hashed_data); EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); assert(mdctx != NULL); EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL); EVP_DigestUpdate(mdctx, data, sizeof(data) - 1); EVP_DigestFinal_ex(mdctx, hashed_data, &hashed_data_len); EVP_MD_CTX_destroy(mdctx); uint16_t wrapping_key_id = 0; // ID 0 lets the device generate an ID yrc = yh_util_generate_wrap_key(session, &wrapping_key_id, key_label, domain_five, &capabilities, YH_ALGO_AES256_CCM_WRAP, &delegated_capabilities); assert(yrc == YHR_SUCCESS); printf("Generated wrapping key with ID %04x\n", wrapping_key_id); memset(capabilities.capabilities, 0, YH_CAPABILITIES_LEN); yrc = yh_string_to_capabilities("sign-ecdsa:sign-eddsa:sign-pkcs:sign-pss:exportable-under-wrap", &capabilities); assert(yrc == YHR_SUCCESS); uint16_t key_id_before = 0; // ID 0 lets the device generate an ID yrc = yh_util_generate_ec_key(session, &key_id_before, key_label, domain_five, &capabilities, YH_ALGO_EC_P256); assert(yrc == YHR_SUCCESS); printf("Generated ec key with ID %04x\n", key_id_before); uint8_t public_key_before[1024]; size_t public_key_before_len = sizeof(public_key_before); yrc = yh_util_get_public_key(session, key_id_before, public_key_before, &public_key_before_len, NULL); assert(yrc == YHR_SUCCESS); memmove(public_key_before + 1, public_key_before, public_key_before_len); public_key_before[0] = 0x04; // hack to make it a valid ec pubkey.. public_key_before_len++; printf("Public ec key before (%zu bytes) is:", public_key_before_len); for (unsigned int i = 0; i < public_key_before_len; i++) { printf(" %02x", public_key_before[i]); } printf("\n"); uint8_t signature_before[512]; size_t signature_before_len = sizeof(signature_before); yrc = yh_util_sign_ecdsa(session, key_id_before, hashed_data, hashed_data_len, signature_before, &signature_before_len); assert(yrc == YHR_SUCCESS); printf("ECDSA signature before (%zu bytes) is:", signature_before_len); for (unsigned int i = 0; i < signature_before_len; i++) { printf(" %02x", signature_before[i]); } printf("\n"); int nid = algo2nid(YH_ALGO_EC_P256); EC_GROUP *group = EC_GROUP_new_by_curve_name(nid); assert(group != NULL); EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); EC_POINT *point = EC_POINT_new(group); EC_POINT_oct2point(group, point, public_key_before, public_key_before_len, NULL); EC_KEY *eckey = EC_KEY_new(); EC_KEY_set_group(eckey, group); EC_KEY_set_public_key(eckey, point); assert(ECDSA_verify(0, hashed_data, hashed_data_len, signature_before, signature_before_len, eckey) == 1); printf("ECDSA Signature before successfully verified\n"); EC_POINT_free(point); EC_KEY_free(eckey); uint8_t wrapped_object[2048]; size_t wrapped_object_len = sizeof(wrapped_object); yh_object_type object_type_after; yrc = yh_util_export_wrapped(session, wrapping_key_id, YH_ASYMMETRIC_KEY, key_id_before, wrapped_object, &wrapped_object_len); assert(yrc == YHR_SUCCESS); printf("Wrapped object (%zu bytes) is:", wrapped_object_len); for (unsigned int i = 0; i < wrapped_object_len; i++) { printf(" %02x", wrapped_object[i]); } printf("\n"); yrc = yh_util_delete_object(session, key_id_before, YH_ASYMMETRIC_KEY); assert(yrc == YHR_SUCCESS); printf("Successfully deleted ec key with ID %04x\n", key_id_before); uint8_t public_key_after[1024]; size_t public_key_after_len = sizeof(public_key_after); yrc = yh_util_get_public_key(session, key_id_before, public_key_after, &public_key_after_len, NULL); assert(yrc == YHR_DEVICE_OBJECT_NOT_FOUND); printf("Unable to get public key for ec key with ID %04x\n", key_id_before); uint16_t key_id_after; yrc = yh_util_import_wrapped(session, wrapping_key_id, wrapped_object, wrapped_object_len, &object_type_after, &key_id_after); assert(yrc == YHR_SUCCESS); printf("Successfully imported wrapped object with ID %04x\n", key_id_after); if (object_type_after != YH_ASYMMETRIC_KEY) { printf("Unexpected odbject type\n"); exit(EXIT_FAILURE); } if (key_id_before != key_id_after) { printf("ID %04x and %04x do not match\n", key_id_before, key_id_after); exit(EXIT_FAILURE); } else { printf("ID %04x and %04x match\n", key_id_before, key_id_after); } yrc = yh_util_get_public_key(session, key_id_after, public_key_after, &public_key_after_len, NULL); assert(yrc == YHR_SUCCESS); memmove(public_key_after + 1, public_key_after, public_key_after_len); public_key_after[0] = 0x04; // hack to make it a valid ec pubkey.. public_key_after_len++; printf("Public ec key after (%zu bytes) is:", public_key_after_len); for (unsigned int i = 0; i < public_key_after_len; i++) { printf(" %02x", public_key_after[i]); } printf("\n"); if (public_key_before_len != public_key_after_len || memcmp(public_key_before, public_key_after, public_key_before_len) != 0) { printf("Public key before and after do not match\n"); exit(EXIT_FAILURE); } else { printf("Public key before and after match\n"); } uint8_t signature_after[512]; size_t signature_after_len = sizeof(signature_after); yrc = yh_util_sign_ecdsa(session, key_id_after, hashed_data, hashed_data_len, signature_after, &signature_after_len); assert(yrc == YHR_SUCCESS); printf("\nECDSA signature after (%zu bytes) is:", signature_after_len); for (unsigned int i = 0; i < signature_after_len; i++) { printf(" %02x", signature_after[i]); } printf("\n"); point = EC_POINT_new(group); EC_POINT_oct2point(group, point, public_key_after, public_key_after_len, NULL); eckey = EC_KEY_new(); EC_KEY_set_group(eckey, group); EC_KEY_set_public_key(eckey, point); assert(ECDSA_verify(0, hashed_data, hashed_data_len, signature_after, signature_after_len, eckey) == 1); printf("ECDSA Signature after successfully verified\n"); EC_POINT_free(point); EC_KEY_free(eckey); EC_GROUP_free(group); yh_object_descriptor object; yrc = yh_util_get_object_info(session, key_id_after, YH_ASYMMETRIC_KEY, &object); assert(yrc == YHR_SUCCESS); yrc = yh_util_delete_object(session, key_id_after, YH_ASYMMETRIC_KEY); assert(yrc == YHR_SUCCESS); printf("Successfully deleted ec key with ID %04x\n", key_id_after); key_id_before = 0; yrc = yh_util_generate_ed_key(session, &key_id_before, key_label, domain_five, &capabilities, YH_ALGO_EC_ED25519); assert(yrc == YHR_SUCCESS); printf("Generated ed25519 key with ID %04x\n", key_id_before); public_key_before_len = sizeof(public_key_before); yrc = yh_util_get_public_key(session, key_id_before, public_key_before, &public_key_before_len, NULL); assert(yrc == YHR_SUCCESS); printf("Public ed25519 key before (%zu bytes) is:", public_key_before_len); for (unsigned int i = 0; i < public_key_before_len; i++) { printf(" %02x", public_key_before[i]); } printf("\n"); signature_before_len = sizeof(signature_before); yrc = yh_util_sign_eddsa(session, key_id_before, hashed_data, hashed_data_len, signature_before, &signature_before_len); assert(yrc == YHR_SUCCESS); printf("Signature (%zu bytes) is:", signature_before_len); for (unsigned int i = 0; i < signature_before_len; i++) { printf(" %02x", signature_before[i]); } printf("\n"); assert(signature_before_len == 64); #if (OPENSSL_VERSION_NUMBER < 0x10101000L) || defined(LIBRESSL_VERSION_NUMBER) printf("Signature check skipped for ed25519 key\n"); #else EVP_PKEY *edkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, 0, public_key_before, public_key_before_len); assert(edkey != NULL); EVP_MD_CTX *edmdctx = EVP_MD_CTX_new(); assert(edmdctx != NULL); assert(EVP_DigestVerifyInit(edmdctx, NULL, NULL, NULL, edkey) > 0); assert(EVP_DigestVerify(edmdctx, signature_before, signature_before_len, hashed_data, hashed_data_len) > 0); EVP_MD_CTX_free(edmdctx); EVP_PKEY_free(edkey); #endif wrapped_object_len = sizeof(wrapped_object); yrc = yh_util_export_wrapped(session, wrapping_key_id, YH_ASYMMETRIC_KEY, key_id_before, wrapped_object, &wrapped_object_len); assert(yrc == YHR_SUCCESS); printf("Wrapped object (%zu bytes) is:", wrapped_object_len); for (unsigned int i = 0; i < wrapped_object_len; i++) { printf(" %02x", wrapped_object[i]); } printf("\n"); yrc = yh_util_delete_object(session, key_id_before, YH_ASYMMETRIC_KEY); assert(yrc == YHR_SUCCESS); printf("Successfully deleted ed25519 key with ID %04x\n", key_id_before); public_key_after_len = sizeof(public_key_after); yrc = yh_util_get_public_key(session, key_id_before, public_key_after, &public_key_after_len, NULL); assert(yrc == YHR_DEVICE_OBJECT_NOT_FOUND); printf("Unable to get public key for ed25519 key with ID %04x\n", key_id_before); yrc = yh_util_import_wrapped(session, wrapping_key_id, wrapped_object, wrapped_object_len, &object_type_after, &key_id_after); assert(yrc == YHR_SUCCESS); printf("Successfully imported wrapped object with ID %04x\n", key_id_after); if (object_type_after != YH_ASYMMETRIC_KEY) { printf("Unexpected odbject type\n"); exit(EXIT_FAILURE); } if (key_id_before != key_id_after) { printf("ID %04x and %04x do not match\n", key_id_before, key_id_after); exit(EXIT_FAILURE); } else { printf("ID %04x and %04x match\n", key_id_before, key_id_after); } yrc = yh_util_get_public_key(session, key_id_after, public_key_after, &public_key_after_len, NULL); assert(yrc == YHR_SUCCESS); printf("Public ed25519 key after (%zu bytes) is:", public_key_after_len); for (unsigned int i = 0; i < public_key_after_len; i++) { printf(" %02x", public_key_after[i]); } printf("\n"); if (public_key_before_len != public_key_after_len || memcmp(public_key_before, public_key_after, public_key_before_len) != 0) { printf("Public key before and after do not match\n"); exit(EXIT_FAILURE); } else { printf("Public key before and after match\n"); } signature_after_len = sizeof(signature_after); yrc = yh_util_sign_eddsa(session, key_id_after, hashed_data, hashed_data_len, signature_after, &signature_after_len); assert(yrc == YHR_SUCCESS); printf("Signature (%zu bytes) is:", signature_after_len); for (unsigned int i = 0; i < signature_after_len; i++) { printf(" %02x", signature_after[i]); } printf("\n"); assert(signature_after_len == 64); #if (OPENSSL_VERSION_NUMBER < 0x10101000L) || defined(LIBRESSL_VERSION_NUMBER) printf("Signature check skipped for ed25519 key\n"); #else edkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, 0, public_key_after, public_key_after_len); assert(edkey != NULL); edmdctx = EVP_MD_CTX_new(); assert(edmdctx != NULL); assert(EVP_DigestVerifyInit(edmdctx, NULL, NULL, NULL, edkey) > 0); assert(EVP_DigestVerify(edmdctx, signature_after, signature_after_len, hashed_data, hashed_data_len) > 0); EVP_MD_CTX_free(edmdctx); EVP_PKEY_free(edkey); #endif if (signature_before_len != signature_after_len || memcmp(signature_before, signature_after, signature_before_len) != 0) { printf("Signature before and after do not match\n"); exit(EXIT_FAILURE); } else { printf("Signature before and after match\n"); } yrc = yh_util_get_object_info(session, key_id_after, YH_ASYMMETRIC_KEY, &object); assert(yrc == YHR_SUCCESS); yrc = yh_util_delete_object(session, key_id_after, YH_ASYMMETRIC_KEY); assert(yrc == YHR_SUCCESS); printf("Successfully deleted ed25519 key with ID %04x\n", key_id_after); key_id_before = 0; yrc = yh_util_generate_rsa_key(session, &key_id_before, key_label, domain_five, &capabilities, YH_ALGO_RSA_2048); assert(yrc == YHR_SUCCESS); printf("Generated 2048 bit RSA key with ID %04x\n", key_id_before); public_key_before_len = sizeof(public_key_before); yrc = yh_util_get_public_key(session, key_id_before, public_key_before, &public_key_before_len, NULL); assert(yrc == YHR_SUCCESS); printf("Public RSA key before (%zu bytes) is:", public_key_before_len); for (unsigned int i = 0; i < public_key_before_len; i++) { printf(" %02x", public_key_before[i]); } printf("\n"); signature_before_len = sizeof(signature_before); yrc = yh_util_sign_pkcs1v1_5(session, key_id_before, true, hashed_data, hashed_data_len, signature_before, &signature_before_len); assert(yrc == YHR_SUCCESS); printf("Signature (%zu bytes) is:", signature_before_len); for (unsigned int i = 0; i < signature_before_len; i++) { printf(" %02x", signature_before[i]); } printf("\n"); BIGNUM *n = BN_bin2bn(public_key_before, public_key_before_len, NULL); assert(n != NULL); BIGNUM *e = BN_bin2bn((const unsigned char *) "\x01\x00\x01", 3, NULL); assert(e != NULL); RSA *rsa = RSA_new(); assert(RSA_set0_key(rsa, n, e, NULL) != 0); assert(RSA_verify(EVP_MD_type(EVP_sha256()), hashed_data, hashed_data_len, signature_before, signature_before_len, rsa) == 1); printf("RSA signature before successfully verified\n"); RSA_free(rsa); wrapped_object_len = sizeof(wrapped_object); yrc = yh_util_export_wrapped(session, wrapping_key_id, YH_ASYMMETRIC_KEY, key_id_before, wrapped_object, &wrapped_object_len); assert(yrc == YHR_SUCCESS); printf("Wrapped object (%zu bytes) is:", wrapped_object_len); for (unsigned int i = 0; i < wrapped_object_len; i++) { printf(" %02x", wrapped_object[i]); } printf("\n"); yrc = yh_util_delete_object(session, key_id_before, YH_ASYMMETRIC_KEY); assert(yrc == YHR_SUCCESS); printf("Successfully deleted RSA key with ID %04x\n", key_id_before); public_key_after_len = sizeof(public_key_after); yrc = yh_util_get_public_key(session, key_id_before, public_key_after, &public_key_after_len, NULL); assert(yrc == YHR_DEVICE_OBJECT_NOT_FOUND); printf("Unable to get public key for RSA key with ID %04x\n", key_id_before); yrc = yh_util_import_wrapped(session, wrapping_key_id, wrapped_object, wrapped_object_len, &object_type_after, &key_id_after); assert(yrc == YHR_SUCCESS); printf("Successfully imported wrapped object with ID %04x\n", key_id_after); if (object_type_after != YH_ASYMMETRIC_KEY) { printf("Unexpected odbject type\n"); exit(EXIT_FAILURE); } if (key_id_before != key_id_after) { printf("ID %04x and %04x do not match\n", key_id_before, key_id_after); exit(EXIT_FAILURE); } else { printf("ID %04x and %04x match\n", key_id_before, key_id_after); } yrc = yh_util_get_public_key(session, key_id_after, public_key_after, &public_key_after_len, NULL); assert(yrc == YHR_SUCCESS); printf("Public RSA key after (%zu bytes) is:", public_key_after_len); for (unsigned int i = 0; i < public_key_after_len; i++) { printf(" %02x", public_key_after[i]); } printf("\n"); if (public_key_before_len != public_key_after_len || memcmp(public_key_before, public_key_after, public_key_before_len) != 0) { printf("Public key before and after do not match\n"); exit(EXIT_FAILURE); } else { printf("Public key before and after match\n"); } signature_after_len = sizeof(signature_after); yrc = yh_util_sign_pkcs1v1_5(session, key_id_before, true, hashed_data, hashed_data_len, signature_after, &signature_after_len); assert(yrc == YHR_SUCCESS); printf("Signature (%zu bytes) is:", signature_after_len); for (unsigned int i = 0; i < signature_after_len; i++) { printf(" %02x", signature_after[i]); } printf("\n"); n = BN_bin2bn(public_key_after, public_key_after_len, NULL); assert(n != NULL); e = BN_bin2bn((const unsigned char *) "\x01\x00\x01", 3, NULL); assert(e != NULL); rsa = RSA_new(); assert(RSA_set0_key(rsa, n, e, NULL) != 0); assert(RSA_verify(EVP_MD_type(EVP_sha256()), hashed_data, hashed_data_len, signature_after, signature_after_len, rsa) == 1); printf("RSA signature after successfully verified\n"); RSA_free(rsa); yrc = yh_util_get_object_info(session, key_id_after, YH_ASYMMETRIC_KEY, &object); assert(yrc == YHR_SUCCESS); yrc = yh_util_delete_object(session, key_id_after, YH_ASYMMETRIC_KEY); assert(yrc == YHR_SUCCESS); printf("Successfully deleted RSA key with ID %04x\n", key_id_after); yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yh_disconnect(connector); assert(yrc == YHR_SUCCESS); yrc = yh_exit(); assert(yrc == YHR_SUCCESS); return 0; } yubihsm-shell-2.7.1/examples/import_authkey.c0000644000175100017510000000766015133003406020746 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include #include #include #include const char *key_label = "label"; const uint8_t password1[] = "password"; const uint8_t password2[] = "letmein!"; int main(void) { yh_connector *connector = NULL; yh_session *session = NULL; yh_rc yrc = YHR_GENERIC_ERROR; uint16_t authkey = 1; const char *connector_url; connector_url = getenv("DEFAULT_CONNECTOR_URL"); if (connector_url == NULL) { connector_url = DEFAULT_CONNECTOR_URL; } yrc = yh_init(); assert(yrc == YHR_SUCCESS); yrc = yh_init_connector(connector_url, &connector); assert(yrc == YHR_SUCCESS); yrc = yh_connect(connector, 0); assert(yrc == YHR_SUCCESS); yrc = yh_create_session_derived(connector, authkey, password1, sizeof(password1) - 1, false, &session); assert(yrc == YHR_SUCCESS); uint8_t session_id; yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d using Authentication Keys " "%04x\n", session_id, authkey); yh_capabilities capabilities = {{0}}; yrc = yh_string_to_capabilities("get-log-entries", &capabilities); assert(yrc == YHR_SUCCESS); uint16_t domain_five = 0; yrc = yh_string_to_domains("5", &domain_five); assert(yrc == YHR_SUCCESS); uint16_t key_id = 0; // ID 0 lets the device generate an ID yrc = yh_util_import_authentication_key_derived(session, &key_id, key_label, domain_five, &capabilities, &capabilities, password2, sizeof(password2)); assert(yrc == YHR_SUCCESS); printf("Imported Authentication Key with ID %04x\n", key_id); yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); printf("Closed session %02d\n", session_id); yrc = yh_create_session_derived(connector, key_id, password2, sizeof(password2) - 1, false, &session); assert(yrc == YHR_SUCCESS); yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d using Authentication Key " "%04x\n", session_id, key_id); printf("Trying to get log entries\n"); uint16_t unlogged_boot, unlogged_auth; yh_log_entry logs[YH_MAX_LOG_ENTRIES]; size_t n_items = sizeof(logs) / sizeof(yh_log_entry); yrc = yh_util_get_log_entries(session, &unlogged_boot, &unlogged_auth, logs, &n_items); assert(yrc == YHR_SUCCESS); printf("Got %zu log entries: %s\n", n_items, yh_strerror(yrc)); printf("Trying to get 16 bytes of random data\n"); uint8_t data[16]; size_t data_len = sizeof(data); yrc = yh_util_get_pseudo_random(session, 16, data, &data_len); assert(yrc == YHR_DEVICE_INSUFFICIENT_PERMISSIONS); printf("Unable to get random data: %s\n", yh_strerror(yrc)); yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yh_disconnect(connector); assert(yrc == YHR_SUCCESS); yrc = yh_exit(); assert(yrc == YHR_SUCCESS); return 0; } yubihsm-shell-2.7.1/examples/attest.c0000644000175100017510000002452715133003406017207 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include #include #include #include #include #include "openssl-compat.h" #include "util.h" const char attestation_template_file[] = "attestation_template.pem"; const char *key_label = "label"; const uint8_t password[] = "password"; static void print_extension(X509_EXTENSION *extension) { // Quick and dirty solution for printing extensions const uint8_t version[] = {0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xc4, 0x0a, 0x04, 0x01}; const uint8_t serial[] = {0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xc4, 0x0a, 0x04, 0x02}; const uint8_t origin[] = {0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xc4, 0x0a, 0x04, 0x03}; const uint8_t domains[] = {0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xc4, 0x0a, 0x04, 0x04}; const uint8_t capabilities[] = {0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xc4, 0x0a, 0x04, 0x05}; const uint8_t id[] = {0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xc4, 0x0a, 0x04, 0x06}; const uint8_t label[] = {0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xc4, 0x0a, 0x04, 0x09}; ASN1_OBJECT *a_object = X509_EXTENSION_get_object(extension); ASN1_OCTET_STRING *a_value = X509_EXTENSION_get_data(extension); uint8_t object[1024]; uint8_t *ptr = object; if (i2d_ASN1_OBJECT(a_object, NULL) > 1024) { printf("Extension to long.\n"); return; } unsigned int object_len = i2d_ASN1_OBJECT(a_object, &ptr); uint8_t value[1024]; ptr = value; if (i2d_ASN1_OCTET_STRING(a_value, NULL) > 1024) { printf("Extension value to long.\n"); return; } unsigned int value_len = i2d_ASN1_OCTET_STRING(a_value, &ptr); if (object_len == sizeof(version) && memcmp(object, version, sizeof(version)) == 0) { printf("Version:"); } else if (object_len == sizeof(serial) && memcmp(object, serial, sizeof(serial)) == 0) { printf("Serial:"); } else if (object_len == sizeof(origin) && memcmp(object, origin, sizeof(origin)) == 0) { printf("Origin:"); } else if (object_len == sizeof(domains) && memcmp(object, domains, sizeof(domains)) == 0) { printf("Domains:"); } else if (object_len == sizeof(capabilities) && memcmp(object, capabilities, sizeof(capabilities)) == 0) { printf("Capabilities:"); } else if (object_len == sizeof(id) && memcmp(object, id, sizeof(id)) == 0) { printf("ID:"); } else if (object_len == sizeof(label) && memcmp(object, label, sizeof(label)) == 0) { printf("Label:"); } else { printf("Unknown:"); } for (unsigned int i = 0; i < value_len; i++) { printf(" %02x", value[i]); } printf("\n"); } int main(void) { yh_connector *connector = NULL; yh_session *session = NULL; yh_rc yrc = YHR_GENERIC_ERROR; uint16_t authkey = 1; const char *connector_url; connector_url = getenv("DEFAULT_CONNECTOR_URL"); if (connector_url == NULL) { connector_url = DEFAULT_CONNECTOR_URL; } yrc = yh_init(); assert(yrc == YHR_SUCCESS); yrc = yh_init_connector(connector_url, &connector); assert(yrc == YHR_SUCCESS); yrc = yh_connect(connector, 0); assert(yrc == YHR_SUCCESS); yrc = yh_create_session_derived(connector, authkey, password, sizeof(password) - 1, false, &session); assert(yrc == YHR_SUCCESS); uint8_t session_id; yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d\n", session_id); yh_capabilities capabilities = {{0}}; yrc = yh_string_to_capabilities("sign-attestation-certificate", &capabilities); assert(yrc == YHR_SUCCESS); uint16_t domain_five = 0; yrc = yh_string_to_domains("5", &domain_five); assert(yrc == YHR_SUCCESS); uint16_t attesting_key_id = 0; // ID 0 lets the device generate an ID yrc = yh_util_generate_ec_key(session, &attesting_key_id, key_label, domain_five, &capabilities, YH_ALGO_EC_P256); assert(yrc == YHR_SUCCESS); printf("Generated attesting key with ID %04x\n", attesting_key_id); uint8_t public_key[256]; size_t public_key_len = sizeof(public_key) - 1; yh_algorithm algo; yrc = yh_util_get_public_key(session, attesting_key_id, public_key + 1, &public_key_len, &algo); assert(yrc == YHR_SUCCESS); public_key[0] = 0x04; // hack to make it a valid ec pubkey.. public_key_len++; int nid = algo2nid(algo); assert(nid); EC_GROUP *group = EC_GROUP_new_by_curve_name(nid); assert(group != NULL); EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); EC_POINT *point = EC_POINT_new(group); assert(point != NULL); assert(EC_POINT_oct2point(group, point, public_key, public_key_len, NULL)); EC_KEY *eckey = EC_KEY_new(); assert(eckey != NULL); assert(EC_KEY_set_group(eckey, group)); assert(EC_KEY_set_public_key(eckey, point)); EVP_PKEY *attesting_key = EVP_PKEY_new(); assert(attesting_key != NULL); assert(EVP_PKEY_set1_EC_KEY(attesting_key, eckey) == 1); EC_KEY_free(eckey); FILE *fp = fopen(attestation_template_file, "rb"); assert(fp != NULL); X509 *attestation_template = PEM_read_X509(fp, NULL, NULL, NULL); assert(attestation_template != NULL); fclose(fp); uint8_t attestation_template_buffer[3072]; uint16_t attestation_template_buffer_len = i2d_X509(attestation_template, NULL); assert(sizeof(attestation_template_buffer) >= attestation_template_buffer_len); unsigned char *certptr = attestation_template_buffer; i2d_X509(attestation_template, &certptr); X509_free(attestation_template); memset(capabilities.capabilities, 0, YH_CAPABILITIES_LEN); yrc = yh_util_import_opaque(session, &attesting_key_id, key_label, domain_five, &capabilities, YH_ALGO_OPAQUE_X509_CERTIFICATE, attestation_template_buffer, attestation_template_buffer_len); assert(yrc == YHR_SUCCESS); uint8_t tmpbuf[3072]; size_t tmpbuf_len = sizeof(tmpbuf); yrc = yh_util_get_opaque(session, attesting_key_id, tmpbuf, &tmpbuf_len); assert(yrc == YHR_SUCCESS); assert(tmpbuf_len == attestation_template_buffer_len); assert(memcmp(attestation_template_buffer, tmpbuf, tmpbuf_len) == 0); memset(capabilities.capabilities, 0, YH_CAPABILITIES_LEN); yrc = yh_string_to_capabilities("sign-ecdsa", &capabilities); assert(yrc == YHR_SUCCESS); uint16_t attested_key_id = 0; // ID 0 lets the device generate an ID yrc = yh_util_generate_ec_key(session, &attested_key_id, key_label, domain_five, &capabilities, YH_ALGO_EC_P256); assert(yrc == YHR_SUCCESS); printf("Generated attested key with ID %04x\n", attested_key_id); uint8_t attestation[2048]; size_t attestation_len = sizeof(attestation); yrc = yh_util_sign_attestation_certificate(session, attested_key_id, attesting_key_id, attestation, &attestation_len); assert(yrc == YHR_SUCCESS); const unsigned char *ptr = attestation; X509 *x509 = d2i_X509(NULL, &ptr, attestation_len); assert(x509 != NULL); BIO *STDout = BIO_new_fp(stdout, BIO_NOCLOSE); X509_print_ex(STDout, x509, 0, 0); BIO_free(STDout); const STACK_OF(X509_EXTENSION) *extensions_list = X509_get0_extensions(x509); assert(sk_X509_EXTENSION_num(extensions_list) >= 6); for (int i = 0; i < sk_X509_EXTENSION_num(extensions_list); i++) { X509_EXTENSION *extension = sk_X509_EXTENSION_value(extensions_list, i); print_extension(extension); } assert(X509_verify(x509, attesting_key)); X509_free(x509); attestation_len = sizeof(attestation); yrc = yh_util_sign_attestation_certificate(session, attesting_key_id, attesting_key_id, attestation, &attestation_len); assert(yrc == YHR_SUCCESS); ptr = attestation; x509 = d2i_X509(NULL, &ptr, attestation_len); assert(x509 != NULL); STDout = BIO_new_fp(stdout, BIO_NOCLOSE); X509_print_ex(STDout, x509, 0, 0); BIO_free(STDout); extensions_list = X509_get0_extensions(x509); assert(sk_X509_EXTENSION_num(extensions_list) >= 6); for (int i = 0; i < sk_X509_EXTENSION_num(extensions_list); i++) { X509_EXTENSION *extension = sk_X509_EXTENSION_value(extensions_list, i); print_extension(extension); } assert(X509_verify(x509, attesting_key)); #ifdef ATTEST_DEVICE_PUBKEY X509_free(x509); attestation_len = sizeof(attestation); yrc = yh_util_sign_attestation_certificate(session, 0, attesting_key_id, attestation, &attestation_len); assert(yrc == YHR_SUCCESS); ptr = attestation; x509 = d2i_X509(NULL, &ptr, attestation_len); assert(x509 != NULL); STDout = BIO_new_fp(stdout, BIO_NOCLOSE); X509_print_ex(STDout, x509, 0, 0); BIO_free(STDout); extensions_list = X509_get0_extensions(x509); assert(sk_X509_EXTENSION_num(extensions_list) >= 6); for (int i = 0; i < sk_X509_EXTENSION_num(extensions_list); i++) { X509_EXTENSION *extension = sk_X509_EXTENSION_value(extensions_list, i); print_extension(extension); } assert(X509_verify(x509, attesting_key)); #endif X509_free(x509); EVP_PKEY_free(attesting_key); yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yrc = yh_disconnect(connector); assert(yrc == YHR_SUCCESS); yrc = yh_exit(); assert(yrc == YHR_SUCCESS); return 0; } yubihsm-shell-2.7.1/examples/wrap_data.c0000644000175100017510000000635215133003406017641 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include #include #include const char *key_label = "label"; const uint8_t password[] = "password"; const uint8_t clear[] = "test data"; int main(void) { yh_connector *connector = NULL; yh_session *session = NULL; yh_rc yrc = YHR_GENERIC_ERROR; uint16_t authkey = 1; const char *connector_url; connector_url = getenv("DEFAULT_CONNECTOR_URL"); if (connector_url == NULL) { connector_url = DEFAULT_CONNECTOR_URL; } yrc = yh_init(); assert(yrc == YHR_SUCCESS); yrc = yh_init_connector(connector_url, &connector); assert(yrc == YHR_SUCCESS); yrc = yh_connect(connector, 0); assert(yrc == YHR_SUCCESS); yrc = yh_create_session_derived(connector, authkey, password, sizeof(password) - 1, false, &session); assert(yrc == YHR_SUCCESS); uint8_t session_id; yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d\n", session_id); yh_capabilities capabilities = {{0}}; yrc = yh_string_to_capabilities("wrap-data:unwrap-data", &capabilities); assert(yrc == YHR_SUCCESS); yh_capabilities delegated_capabilities = {{0}}; uint16_t domain_five = 0; uint16_t wrapping_key_id = 0; // ID 0 lets the device generate an ID yrc = yh_string_to_domains("5", &domain_five); assert(yrc == YHR_SUCCESS); yrc = yh_util_generate_wrap_key(session, &wrapping_key_id, key_label, domain_five, &capabilities, YH_ALGO_AES256_CCM_WRAP, &delegated_capabilities); assert(yrc == YHR_SUCCESS); printf("Generated wrapping key with ID %04x\n", wrapping_key_id); uint8_t data[1024]; size_t data_len = sizeof(data); yrc = yh_util_wrap_data(session, wrapping_key_id, clear, sizeof(clear), data, &data_len); assert(yrc == YHR_SUCCESS); printf("Data wrapped to length %zu\n", data_len); assert(data_len == sizeof(clear) + YH_CCM_WRAP_OVERHEAD); assert(memcmp(data, clear, sizeof(clear)) != 0); yrc = yh_util_unwrap_data(session, wrapping_key_id, data, data_len, data, &data_len); assert(yrc == YHR_SUCCESS); assert(data_len == sizeof(clear)); assert(memcmp(data, clear, sizeof(clear)) == 0); printf("Data unwrapped successfully\n"); yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yh_disconnect(connector); assert(yrc == YHR_SUCCESS); yrc = yh_exit(); assert(yrc == YHR_SUCCESS); return 0; } yubihsm-shell-2.7.1/examples/import_rsa.c0000644000175100017510000001256515133003406020061 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include #include #include #include #include "util.h" #include "openssl-compat.h" #include const char rsa2048_pvtkey_file[] = "rsa2048_pvtkey.pem"; const char *key_label = "label"; const uint8_t password[] = "password"; const uint8_t data[] = "sudo make me a sandwich"; int main(void) { yh_connector *connector = NULL; yh_session *session = NULL; yh_rc yrc = YHR_GENERIC_ERROR; uint16_t authkey = 1; const char *connector_url; connector_url = getenv("DEFAULT_CONNECTOR_URL"); if (connector_url == NULL) { connector_url = DEFAULT_CONNECTOR_URL; } yrc = yh_init(); assert(yrc == YHR_SUCCESS); yrc = yh_init_connector(connector_url, &connector); assert(yrc == YHR_SUCCESS); yrc = yh_connect(connector, 0); assert(yrc == YHR_SUCCESS); yrc = yh_create_session_derived(connector, authkey, password, sizeof(password) - 1, false, &session); assert(yrc == YHR_SUCCESS); uint8_t session_id; yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d\n", session_id); FILE *fp = fopen(rsa2048_pvtkey_file, "rb"); assert(fp != NULL); yh_algorithm algorithm = 0; uint8_t privkey[2048]; size_t key_material_len = sizeof(privkey); if (!read_file(fp, privkey, &key_material_len)) { assert(false); } bool ret = read_private_key(privkey, key_material_len, &algorithm, privkey, &key_material_len, false); assert(ret == true); assert(algorithm == YH_ALGO_RSA_2048); yh_capabilities capabilities = {{0}}; yrc = yh_string_to_capabilities("sign-pss", &capabilities); assert(yrc == YHR_SUCCESS); uint16_t domain_five = 0; yh_string_to_domains("5", &domain_five); assert(yrc == YHR_SUCCESS); uint16_t key_id = 0; // ID 0 lets the device generate an ID yrc = yh_util_import_rsa_key(session, &key_id, key_label, domain_five, &capabilities, algorithm, privkey, privkey + (key_material_len / 2)); assert(yrc == YHR_SUCCESS); printf("Key imported with ID %04x\n", key_id); printf("Data to sign (%zu bytes) is: %s\n", sizeof(data) - 1, data); EVP_MD_CTX *mdctx = NULL; uint8_t hashed_data[32]; unsigned int hashed_data_len; mdctx = EVP_MD_CTX_create(); assert(mdctx != NULL); EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL); EVP_DigestUpdate(mdctx, data, sizeof(data) - 1); EVP_DigestFinal_ex(mdctx, hashed_data, &hashed_data_len); EVP_MD_CTX_destroy(mdctx); printf("Hash of data (%d bytes) is:", EVP_MD_size(EVP_sha256())); for (unsigned int i = 0; i < hashed_data_len; i++) { printf(" %02x", hashed_data[i]); } printf("\n"); uint8_t signature[512]; size_t signature_len = sizeof(signature); yrc = yh_util_sign_pss(session, key_id, hashed_data, hashed_data_len, signature, &signature_len, 32, YH_ALGO_MGF1_SHA256); assert(yrc == YHR_SUCCESS); printf("Signature (%zu bytes) is:", signature_len); for (unsigned int i = 0; i < signature_len; i++) { printf(" %02x", signature[i]); } printf("\n"); uint8_t public_key[512]; size_t public_key_len = sizeof(public_key); yrc = yh_util_get_public_key(session, key_id, public_key, &public_key_len, NULL); assert(yrc == YHR_SUCCESS); printf("Public key (%zu bytes) is:", public_key_len); for (unsigned int i = 0; i < public_key_len; i++) { printf(" %02x", public_key[i]); } printf("\n"); BIGNUM *n = BN_bin2bn(public_key, public_key_len, NULL); assert(n != NULL); BIGNUM *e = BN_bin2bn((const unsigned char *) "\x01\x00\x01", 3, NULL); assert(e != NULL); RSA *rsa = RSA_new(); assert(RSA_set0_key(rsa, n, e, NULL) != 0); EVP_PKEY *key = EVP_PKEY_new(); assert(EVP_PKEY_assign_RSA(key, rsa) == 1); EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(key, NULL); assert(ctx != NULL); assert(EVP_PKEY_verify_init(ctx) == 1); assert(EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) == 1); assert(EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) == 1); assert(EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, 32) == 1); assert(EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha256()) == 1); if (EVP_PKEY_verify(ctx, signature, signature_len, hashed_data, hashed_data_len) == 1) { printf("Signature successfully verified\n"); } else { printf("Unable to verify signature\n"); } EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(key); yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yh_disconnect(connector); assert(yrc == YHR_SUCCESS); yrc = yh_exit(); assert(yrc == YHR_SUCCESS); return 0; } yubihsm-shell-2.7.1/examples/p256_pvtkey.pem0000644000175100017510000000045615133003406020333 0ustar runnerrunner-----BEGIN EC PARAMETERS----- BggqhkjOPQMBBw== -----END EC PARAMETERS----- -----BEGIN EC PRIVATE KEY----- MHcCAQEEIHj8HDHmb3sE2LbjB4iOkfh2wngiUJX340mzn9viEm/ZoAoGCCqGSM49 AwEHoUQDQgAESfiuLv9xV/VNf2wLgrMba2jLcjY/DmstGEs2sC9nbR+OhUUia3n1 f/TdJE466eFZ9MIaZNmRsrkwxWbZ1w7yWQ== -----END EC PRIVATE KEY----- yubihsm-shell-2.7.1/examples/generate_hmac.c0000644000175100017510000000703615133003406020461 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include #include #include #include const char *key_label = "label"; const uint8_t password[] = "password"; const uint8_t data[] = "sudo make me a sandwich"; int main(void) { yh_connector *connector = NULL; yh_session *session = NULL; yh_rc yrc = YHR_GENERIC_ERROR; uint16_t authkey = 1; const char *connector_url; connector_url = getenv("DEFAULT_CONNECTOR_URL"); if (connector_url == NULL) { connector_url = DEFAULT_CONNECTOR_URL; } yrc = yh_init(); assert(yrc == YHR_SUCCESS); yrc = yh_init_connector(connector_url, &connector); assert(yrc == YHR_SUCCESS); yrc = yh_connect(connector, 0); assert(yrc == YHR_SUCCESS); yrc = yh_create_session_derived(connector, authkey, password, sizeof(password) - 1, false, &session); assert(yrc == YHR_SUCCESS); uint8_t session_id; yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d using Authentication Key " "%04x\n", session_id, authkey); yh_capabilities capabilities = {{0}}; yrc = yh_string_to_capabilities("sign-hmac:verify-hmac", &capabilities); assert(yrc == YHR_SUCCESS); uint16_t domain_five = 0; yrc = yh_string_to_domains("5", &domain_five); assert(yrc == YHR_SUCCESS); uint16_t key_id = 0; // ID 0 lets the device generate an ID yrc = yh_util_generate_hmac_key(session, &key_id, key_label, domain_five, &capabilities, YH_ALGO_HMAC_SHA256); assert(yrc == YHR_SUCCESS); printf("Generated HMAC-SHA256 key with ID %04x\n", key_id); uint8_t hmac_data[64]; size_t hmac_data_len = sizeof(hmac_data); yrc = yh_util_sign_hmac(session, key_id, data, sizeof(data) - 1, hmac_data, &hmac_data_len); assert(yrc == YHR_SUCCESS); printf("HMAC of data (%zu bytes) is:", hmac_data_len); for (size_t i = 0; i < hmac_data_len; i++) { printf(" %02x", hmac_data[i]); } printf("\n"); bool verified; yrc = yh_util_verify_hmac(session, key_id, hmac_data, hmac_data_len, data, sizeof(data) - 1, &verified); assert(yrc == YHR_SUCCESS); if (verified == true) { printf("Successfully verified HMAC\n"); } else { printf("Unable to verify HMAC\n"); } hmac_data[0] += 1; yrc = yh_util_verify_hmac(session, key_id, hmac_data, hmac_data_len, data, sizeof(data) - 1, &verified); assert(yrc == YHR_SUCCESS); if (verified == true) { printf("Successfully verified HMAC\n"); } else { printf("Unable to verify HMAC\n"); } yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yh_disconnect(connector); assert(yrc == YHR_SUCCESS); yrc = yh_exit(); assert(yrc == YHR_SUCCESS); return 0; } yubihsm-shell-2.7.1/examples/p11_generate_rsa.c0000644000175100017510000000775615133003406021030 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include #include #include int main(int argc, char *argv[]) { if (argc != 2) { fprintf(stderr, "usage: p11 /path/to/yubihsm_pkcs11/module\n"); exit(EXIT_FAILURE); } CK_C_GetFunctionList fn; void *handle = dlopen(argv[1], RTLD_NOW | RTLD_GLOBAL); assert(handle != NULL); *(void **) (&fn) = dlsym(handle, "C_GetFunctionList"); assert(fn != NULL); CK_FUNCTION_LIST_PTR p11; CK_RV rv = fn(&p11); assert(rv == CKR_OK); rv = p11->C_Initialize(NULL_PTR); assert(rv == CKR_OK); CK_SESSION_HANDLE session; rv = p11->C_OpenSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &session); assert(rv == CKR_OK); char password[] = "0001password"; rv = p11->C_Login(session, CKU_USER, (CK_UTF8CHAR_PTR) password, (CK_ULONG) strlen(password)); assert(rv == CKR_OK); CK_MECHANISM mechanism = {CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0}; CK_ULONG modulus = 2048; CK_BYTE exponent[] = {0x00, 0x1, 0x0, 0x1}; // 65537 CK_BYTE id[] = {0, 0}; CK_BBOOL ck_true = CK_TRUE; CK_BBOOL ck_false = CK_FALSE; char pub_label[] = "RSA 2048 key"; char priv_label[] = "RSA 2048 key"; CK_ATTRIBUTE publicKeyTemplate[] = { {CKA_ENCRYPT, &ck_true, sizeof(ck_true)}, {CKA_DECRYPT, &ck_false, sizeof(ck_false)}, {CKA_SIGN, &ck_false, sizeof(ck_false)}, {CKA_VERIFY, &ck_true, sizeof(ck_true)}, {CKA_WRAP, &ck_true, sizeof(ck_true)}, {CKA_UNWRAP, &ck_false, sizeof(ck_false)}, {CKA_TOKEN, &ck_false, sizeof(ck_false)}, {CKA_PRIVATE, &ck_false, sizeof(ck_false)}, {CKA_EXTRACTABLE, &ck_true, sizeof(ck_true)}, {CKA_MODIFIABLE, &ck_false, sizeof(ck_false)}, {CKA_COPYABLE, &ck_false, sizeof(ck_false)}, {CKA_DESTROYABLE, &ck_true, sizeof(ck_true)}, {CKA_ID, id, sizeof(id)}, {CKA_MODULUS_BITS, &modulus, sizeof(modulus)}, {CKA_PUBLIC_EXPONENT, exponent, sizeof(exponent)}, {CKA_LABEL, pub_label, sizeof(pub_label)}, }; CK_ULONG publicKeyAttributeCount = sizeof(publicKeyTemplate) / sizeof(publicKeyTemplate[0]); CK_ATTRIBUTE privateKeyTemplate[] = { {CKA_ENCRYPT, &ck_false, sizeof(ck_false)}, {CKA_DECRYPT, &ck_true, sizeof(ck_true)}, {CKA_SIGN, &ck_true, sizeof(ck_true)}, {CKA_VERIFY, &ck_false, sizeof(ck_false)}, {CKA_WRAP, &ck_false, sizeof(ck_false)}, {CKA_UNWRAP, &ck_true, sizeof(ck_true)}, {CKA_TOKEN, &ck_true, sizeof(ck_true)}, {CKA_PRIVATE, &ck_true, sizeof(ck_true)}, {CKA_EXTRACTABLE, &ck_true, sizeof(ck_true)}, {CKA_MODIFIABLE, &ck_false, sizeof(ck_false)}, {CKA_COPYABLE, &ck_false, sizeof(ck_false)}, {CKA_DESTROYABLE, &ck_true, sizeof(ck_true)}, {CKA_ID, id, sizeof(id)}, {CKA_LABEL, priv_label, sizeof(priv_label)}, }; CK_ULONG privateKeyAttributeCount = sizeof(privateKeyTemplate) / sizeof(privateKeyTemplate[0]); CK_OBJECT_HANDLE publicKey, privateKey; rv = p11->C_GenerateKeyPair(session, &mechanism, publicKeyTemplate, publicKeyAttributeCount, privateKeyTemplate, privateKeyAttributeCount, &publicKey, &privateKey); assert(rv == CKR_OK); rv = p11->C_Logout(session); assert(rv == CKR_OK); rv = p11->C_CloseSession(session); assert(rv == CKR_OK); rv = p11->C_Finalize(NULL); assert(rv == CKR_OK); dlclose(handle); return 0; } yubihsm-shell-2.7.1/examples/CMakeLists.txt0000644000175100017510000001335215133003406020271 0ustar runnerrunner# # Copyright 2015-2018 Yubico AB # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # include(${CMAKE_SOURCE_DIR}/cmake/openssl.cmake) find_libcrypto() set ( SOURCE_IMPORT_RSA import_rsa.c ../common/hash.c ../common/util.c ../common/openssl-compat.c ) set ( SOURCE_GENERATE_EC generate_ec.c ../common/hash.c ../common/util.c ../common/openssl-compat.c ) set ( SOURCEINFO info.c ) set ( SOURCE_IMPORT_AUTHKEY import_authkey.c ) set ( SOURCE_GENERATE_HMAC generate_hmac.c ) set ( SOURCE_WRAP wrap.c ../common/util.c ../common/hash.c ../common/openssl-compat.c ) set ( SOURCE_WRAP_DATA wrap_data.c ) set ( SOURCE_ATTEST attest.c ../common/util.c ../common/hash.c ../common/openssl-compat.c ) set ( SOURCE_YUBICO_OTP yubico_otp.c ) set ( SOURCE_ECHO echo.c ) set ( SOURCE_ASYM_AUTH asym_auth.c ../common/openssl-compat.c ) set ( SOURCE_IMPORT_EC import_ec.c ../common/hash.c ../common/util.c ../common/openssl-compat.c ) set ( SOURCE_GENERATE_RSA generate_rsa.c ../common/openssl-compat.c ) set ( SOURCE_LOGS logs.c ../common/hash.c ../common/util.c ../common/openssl-compat.c ) set ( SOURCE_SSH ssh.c ../common/hash.c ../common/util.c ../common/openssl-compat.c ) set ( SOURCE_DECRYPT_RSA decrypt_rsa.c ../common/hash.c ../common/util.c ../common/openssl-compat.c ) set ( SOURCE_P11_GENERATE_RSA p11_generate_rsa.c ../common/openssl-compat.c ) set ( SOURCE_DECRYPT_EC decrypt_ec.c ../common/hash.c ../common/util.c ../common/openssl-compat.c ) set ( SOURCE_IMPORT_ED import_ed.c ../common/hash.c ../common/util.c ../common/openssl-compat.c ) set ( SOURCE_CHANGE_AUTHKEY change_authkey.c ) set( SOURCE_ENCRYPT_AES encrypt_aes.c ) include_directories ( ${LIBCRYPTO_INCLUDEDIR} ${CMAKE_CURRENT_SOURCE_DIR}/../lib ${CMAKE_CURRENT_SOURCE_DIR}/../pkcs11 ${CMAKE_CURRENT_SOURCE_DIR}/../common ) configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/rsa2048_pvtkey.pem ${CMAKE_CURRENT_BINARY_DIR}/rsa2048_pvtkey.pem COPYONLY) configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/p256_pvtkey.pem ${CMAKE_CURRENT_BINARY_DIR}/p256_pvtkey.pem COPYONLY) configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/attestation_template.pem ${CMAKE_CURRENT_BINARY_DIR}/attestation_template.pem COPYONLY) configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/ssh_ca_pvtkey.pem ${CMAKE_CURRENT_BINARY_DIR}/ssh_ca_pvtkey.pem COPYONLY) configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/ssh_req.dat ${CMAKE_CURRENT_BINARY_DIR}/ssh_req.dat COPYONLY) configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/ed25519_pvtkey.pem ${CMAKE_CURRENT_BINARY_DIR}/ed25519_pvtkey.pem COPYONLY) add_executable (import_rsa ${SOURCE_IMPORT_RSA}) target_link_libraries ( import_rsa ${LIBCRYPTO_LDFLAGS} yubihsm ) add_executable (generate_ec ${SOURCE_GENERATE_EC}) target_link_libraries ( generate_ec ${LIBCRYPTO_LDFLAGS} yubihsm ) add_executable (info ${SOURCEINFO}) target_link_libraries ( info ${LIBCRYPTO_LDFLAGS} yubihsm ) add_executable (import_authkey ${SOURCE_IMPORT_AUTHKEY}) target_link_libraries ( import_authkey ${LIBCRYPTO_LDFLAGS} yubihsm ) add_executable (generate_hmac ${SOURCE_GENERATE_HMAC}) target_link_libraries ( generate_hmac ${LIBCRYPTO_LDFLAGS} yubihsm ) add_executable (wrap ${SOURCE_WRAP}) target_link_libraries ( wrap ${LIBCRYPTO_LDFLAGS} yubihsm ) add_executable (wrap_data ${SOURCE_WRAP_DATA}) target_link_libraries ( wrap_data ${LIBCRYPTO_LDFLAGS} yubihsm ) add_executable (attest ${SOURCE_ATTEST}) target_link_libraries ( attest ${LIBCRYPTO_LDFLAGS} yubihsm ) add_executable (yubico_otp ${SOURCE_YUBICO_OTP}) target_link_libraries ( yubico_otp ${LIBCRYPTO_LDFLAGS} yubihsm ) add_executable (echo ${SOURCE_ECHO}) target_link_libraries ( echo ${LIBCRYPTO_LDFLAGS} yubihsm ) add_executable (asym_auth ${SOURCE_ASYM_AUTH}) target_link_libraries ( asym_auth ${LIBCRYPTO_LDFLAGS} yubihsm ) add_executable (import_ec ${SOURCE_IMPORT_EC}) target_link_libraries ( import_ec ${LIBCRYPTO_LDFLAGS} yubihsm ) add_executable (generate_rsa ${SOURCE_GENERATE_RSA}) target_link_libraries ( generate_rsa ${LIBCRYPTO_LDFLAGS} yubihsm ) add_executable (logs ${SOURCE_LOGS}) target_link_libraries ( logs ${LIBCRYPTO_LDFLAGS} yubihsm ) add_executable (ssh ${SOURCE_SSH}) target_link_libraries ( ssh ${LIBCRYPTO_LDFLAGS} yubihsm ) add_executable (decrypt_rsa ${SOURCE_DECRYPT_RSA}) target_link_libraries ( decrypt_rsa ${LIBCRYPTO_LDFLAGS} yubihsm ) add_executable (decrypt_ec ${SOURCE_DECRYPT_EC}) target_link_libraries ( decrypt_ec ${LIBCRYPTO_LDFLAGS} yubihsm ) add_executable (import_ed ${SOURCE_IMPORT_ED}) target_link_libraries ( import_ed ${LIBCRYPTO_LDFLAGS} yubihsm ) add_executable (change_authkey ${SOURCE_CHANGE_AUTHKEY}) target_link_libraries ( change_authkey ${LIBCRYPTO_LDFLAGS} yubihsm ) add_executable(encrypt_aes ${SOURCE_ENCRYPT_AES}) target_link_libraries( encrypt_aes yubihsm ) if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Windows") add_executable (p11_generate_rsa ${SOURCE_P11_GENERATE_RSA}) target_link_libraries ( p11_generate_rsa ${LIBCRYPTO_LDFLAGS} dl ) endif() yubihsm-shell-2.7.1/examples/asym_auth.c0000644000175100017510000001441415133003406017667 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include #include const uint8_t password[] = "password"; const uint8_t data[] = "sudo make me a sandwich"; static int compare_algorithm(const void *a, const void *b) { return (*(const yh_algorithm *) a - *(const yh_algorithm *) b); } int main(void) { yh_connector *connector = NULL; yh_rc yrc = YHR_GENERIC_ERROR; const char *connector_url = getenv("DEFAULT_CONNECTOR_URL"); if (connector_url == NULL) { connector_url = DEFAULT_CONNECTOR_URL; } yrc = yh_init(); if (yrc != YHR_SUCCESS) { fprintf(stderr, "unable to initialize yubihsm: %s\n", yh_strerror(yrc)); exit(EXIT_FAILURE); } yrc = yh_init_connector(connector_url, &connector); assert(yrc == YHR_SUCCESS); yrc = yh_connect(connector, 0); assert(yrc == YHR_SUCCESS); char *received_url; yrc = yh_get_connector_address(connector, &received_url); assert(yrc == YHR_SUCCESS); yh_set_verbosity(connector, YH_VERB_ALL); uint8_t d_major, d_minor, d_patch; uint32_t serial; uint8_t log_total, log_used; yh_algorithm algorithms[YH_MAX_ALGORITHM_COUNT]; size_t n_algorithms = sizeof(algorithms); yrc = yh_util_get_device_info(connector, &d_major, &d_minor, &d_patch, &serial, &log_total, &log_used, algorithms, &n_algorithms); assert(yrc == YHR_SUCCESS); yh_algorithm key = YH_ALGO_EC_P256_YUBICO_AUTHENTICATION; if (!bsearch(&key, algorithms, n_algorithms, sizeof(key), compare_algorithm)) { fprintf(stderr, "Skipping this test because the device does not support " "aymmetric authentication\n"); exit(EXIT_SUCCESS); } printf("Send a plain (unencrypted, unauthenticated) echo command\n"); uint16_t data_len = sizeof(data) - 1; uint8_t response[sizeof(data)] = {0}; size_t response_len = sizeof(response); yh_cmd response_cmd; yrc = yh_send_plain_msg(connector, YHC_ECHO, data, data_len, &response_cmd, response, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to send ECHO command: %s\n", yh_strerror(yrc)); exit(EXIT_FAILURE); } printf("Response (%zu bytes): \"%s\"\n", response_len, response); yh_session *session = NULL; uint16_t authkey = 1; yrc = yh_create_session_derived(connector, authkey, password, sizeof(password) - 1, false, &session); assert(yrc == YHR_SUCCESS); authkey = 2; yh_util_delete_object(session, authkey, YH_AUTHENTICATION_KEY); // Ignore result here uint8_t sk_oce[YH_EC_P256_PRIVKEY_LEN], pk_oce[YH_EC_P256_PUBKEY_LEN]; yrc = yh_util_generate_ec_p256_key(sk_oce, sizeof(sk_oce), pk_oce, sizeof(pk_oce)); assert(yrc == YHR_SUCCESS); yh_capabilities caps = {{0}}; yrc = yh_string_to_capabilities("change-authentication-key,get-pseudo-random", &caps); assert(yrc == YHR_SUCCESS); // The public key is imported without the uncompressed point marker (value // 0x04), so skip the first byte yrc = yh_util_import_authentication_key(session, &authkey, "EC Auth Key", 0xffff, &caps, &caps, pk_oce + 1, sizeof(pk_oce) - 1, NULL, 0); assert(yrc == YHR_SUCCESS); yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); uint8_t pk_sd[YH_EC_P256_PUBKEY_LEN]; size_t pk_sd_len = sizeof(pk_sd); yrc = yh_util_get_device_pubkey(connector, pk_sd, &pk_sd_len, NULL); assert(yrc == YHR_SUCCESS); yrc = yh_create_session_asym(connector, authkey, sk_oce, sizeof(sk_oce), pk_sd, pk_sd_len, &session); assert(yrc == YHR_SUCCESS); uint8_t session_id; yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d\n", session_id); uint8_t buf[32]; size_t buf_len = sizeof(buf); yrc = yh_util_get_pseudo_random(session, buf_len, buf, &buf_len); assert(yrc == YHR_SUCCESS); printf("Send a secure echo command\n"); uint8_t response2[sizeof(data)] = {0}; size_t response2_len = sizeof(response); yh_cmd response2_cmd; yrc = yh_send_secure_msg(session, YHC_ECHO, data, data_len, &response2_cmd, response2, &response2_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to send ECHO command: %s\n", yh_strerror(yrc)); exit(EXIT_FAILURE); } printf("Response (%zu bytes): \"%s\"\n", response_len, response); assert(response_len == response2_len); assert(memcmp(response, response2, response_len) == 0); yrc = yh_util_generate_ec_p256_key(sk_oce, sizeof(sk_oce), pk_oce, sizeof(pk_oce)); assert(yrc == YHR_SUCCESS); yrc = yh_util_change_authentication_key(session, &authkey, pk_oce + 1, sizeof(pk_oce) - 1, NULL, 0); assert(yrc == YHR_SUCCESS); yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yrc = yh_create_session_asym(connector, authkey, sk_oce, sizeof(sk_oce), pk_sd, pk_sd_len, &session); assert(yrc == YHR_SUCCESS); buf_len = sizeof(buf); yrc = yh_util_get_pseudo_random(session, buf_len, buf, &buf_len); assert(yrc == YHR_SUCCESS); yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yrc = yh_disconnect(connector); assert(yrc == YHR_SUCCESS); yrc = yh_exit(); assert(yrc == YHR_SUCCESS); return 0; } yubihsm-shell-2.7.1/examples/attestation_template.pem0000644000175100017510000000207215133003406022463 0ustar runnerrunner-----BEGIN CERTIFICATE----- MIIC8TCCAdmgAwIBAgIJAI4siOgx84SNMA0GCSqGSIb3DQEBCwUAMA8xDTALBgNV BAMMBHRlc3QwHhcNMTcwMzE3MTMwODAyWhcNMjcwMzE1MTMwODAyWjAPMQ0wCwYD VQQDDAR0ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv0J9YugQ 3po8PtkrhQsq4aUbU0y2MtruYvZjRG0tMMtTrE92FXqrBltL+LXjhC6nOcgkjb4U JFdJzK+QsQ3jpJNOpGWSWHCrEk8CVJnl2klq6vhlcSTlojHu912WYdiCudA0KhQ+ ffFhfGpAItctLMvaD7aS01l/OKzXAUkCv+8f2p+/+2I7mEnv88gOsisf78kqRPrQ b1xuRvHdNsehtxo+VN5bbKICkNskd18EloX46LjYi9oQ0zihmm24yGYPWUmDv1zm CBlM2AT2kHxHtHMl+DyewZERYtHKUN3irzyEq/9H2TxsfsYk2wR8QtAADU+mMe9M ne9lXrkgusx4RQIDAQABo1AwTjAdBgNVHQ4EFgQUGzIsrm1ZNd37V7vCLXolfTtM xEEwHwYDVR0jBBgwFoAUGzIsrm1ZNd37V7vCLXolfTtMxEEwDAYDVR0TBAUwAwEB /zANBgkqhkiG9w0BAQsFAAOCAQEAh7S+9c8Mcg/aK6qhQ/m0WJUSW5W4QL0p3fwG ettK+4tntI6ufgaJgxgvG8ucrcOJ/j/s7ZDqJ7MjRsZm391616oZixkPzCrBhWgr 3Vv6gFtnxXrwQMdgvzpKhtSrxjoDyUnFLs14H/e/L0+qGAlAN2adHHha7zouaWwY +KyyK5sX2m/yQg/uQm4KeVqz3wsA6zJXIg0EEH/ISj7JBCCyux3ouS3x/z+43Hl4 DzFJtJotn34HKe02gcCd4qxginQJJ84j2G4JZ42deVFPPp6dbHIuLFHunCH8HTkA jpI5R8+6LS+5+gci9J5OaVMAgvy6cYqx85lbaoyXdXB8aGLkNw== -----END CERTIFICATE----- yubihsm-shell-2.7.1/examples/logs.c0000644000175100017510000001334415133003406016642 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include #include #include #include #include "util.h" #include #define N_OPERATIONS 5 const uint8_t password[] = "password"; int main(void) { yh_connector *connector = NULL; yh_session *session = NULL; yh_rc yrc = YHR_GENERIC_ERROR; uint16_t authkey = 1; const char *connector_url; connector_url = getenv("DEFAULT_CONNECTOR_URL"); if (connector_url == NULL) { connector_url = DEFAULT_CONNECTOR_URL; } yrc = yh_init(); assert(yrc == YHR_SUCCESS); yrc = yh_init_connector(connector_url, &connector); assert(yrc == YHR_SUCCESS); yrc = yh_connect(connector, 0); assert(yrc == YHR_SUCCESS); yrc = yh_create_session_derived(connector, authkey, password, sizeof(password) - 1, false, &session); assert(yrc == YHR_SUCCESS); uint8_t session_id; yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d\n", session_id); printf("Flushing existing logs\n"); uint16_t unlogged_boot, unlogged_auth; yh_log_entry logs[YH_MAX_LOG_ENTRIES]; size_t n_items = sizeof(logs) / sizeof(yh_log_entry); yh_log_entry last_previous_log; yh_log_entry *last_previous_log_ptr = &last_previous_log; uint8_t option[256]; size_t option_len; option[0] = YHC_SET_OPTION; option[1] = 0x01; option[2] = YHC_SET_LOG_INDEX; option[3] = 0x01; option[4] = YHC_GET_OBJECT_INFO; option[5] = 0x01; option_len = 2 * 3; yrc = yh_util_set_option(session, YH_OPTION_COMMAND_AUDIT, option_len, option); assert(yrc == YHR_SUCCESS); yrc = yh_util_get_log_entries(session, &unlogged_boot, &unlogged_auth, logs, &n_items); assert(yrc == YHR_SUCCESS); if (n_items != 0) { memcpy(&last_previous_log, logs + n_items - 1, sizeof(yh_log_entry)); } else { last_previous_log_ptr = NULL; } uint16_t last_index = logs[n_items - 1].number; yrc = yh_util_set_log_index(session, last_index); assert(yrc == YHR_SUCCESS); printf("Performing some operations\n"); for (uint16_t i = 0; i < N_OPERATIONS; i++) { yh_object_descriptor descriptor; yrc = yh_util_get_object_info(session, authkey, YH_AUTHENTICATION_KEY, &descriptor); assert(yrc == YHR_SUCCESS); } printf("Getting logs\n"); n_items = sizeof(logs) / sizeof(yh_log_entry); yrc = yh_util_get_log_entries(session, &unlogged_boot, &unlogged_auth, logs, &n_items); assert(yrc == YHR_SUCCESS); assert(n_items == N_OPERATIONS + 1); fprintf(stdout, "%d unlogged boots found\n", unlogged_boot); fprintf(stdout, "%d unlogged authentications found\n", unlogged_auth); char digest_buf[(2 * YH_LOG_DIGEST_SIZE) + 1]; if (n_items == 0) { fprintf(stdout, "No logs to extract\n"); return 0; } else if (n_items == 1) { fprintf(stdout, "Found 1 item\n"); } else { fprintf(stdout, "Found %zu items\n", n_items); } for (uint16_t i = 0; i < n_items; i++) { format_digest(logs[i].digest, digest_buf, YH_LOG_DIGEST_SIZE); fprintf(stdout, "item: %5u -- cmd: 0x%02x -- length: %4u -- session key: " "0x%04x -- target key: 0x%04x -- second key: 0x%04x -- " "result: 0x%02x -- tick: %lu -- hash: %s\n", logs[i].number, logs[i].command, logs[i].length, logs[i].session_key, logs[i].target_key, logs[i].second_key, logs[i].result, (unsigned long) logs[i].systick, digest_buf); } bool ret = yh_verify_logs(logs, n_items, last_previous_log_ptr); assert(ret == true); printf("Logs correctly verified\n"); option[0] = YHC_SET_OPTION; option[1] = 0x00; option_len = 2; yrc = yh_util_set_option(session, YH_OPTION_COMMAND_AUDIT, option_len, option); assert(yrc == YHR_SUCCESS); option_len = sizeof(option); yrc = yh_util_get_option(session, YH_OPTION_COMMAND_AUDIT, option, &option_len); assert(yrc == YHR_SUCCESS); assert(option_len % 2 == 0); bool option_found = false; for (size_t i = 0; i < option_len; i += 2) { if (option[i] == YHC_SET_OPTION) { assert(option[i + 1] == 0); option_found = true; break; } } assert(option_found == true); option[0] = YHC_SET_OPTION; option[1] = 0x01; option_len = 2; yrc = yh_util_set_option(session, YH_OPTION_COMMAND_AUDIT, option_len, option); assert(yrc == YHR_SUCCESS); option_len = sizeof(option); yrc = yh_util_get_option(session, YH_OPTION_COMMAND_AUDIT, option, &option_len); assert(yrc == YHR_SUCCESS); assert(option_len % 2 == 0); option_found = false; for (size_t i = 0; i < option_len; i += 2) { if (option[i] == YHC_SET_OPTION) { assert(option[i + 1] == 1); option_found = true; break; } } assert(option_found == true); yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yh_disconnect(connector); assert(yrc == YHR_SUCCESS); yrc = yh_exit(); assert(yrc == YHR_SUCCESS); return EXIT_SUCCESS; } yubihsm-shell-2.7.1/examples/ssh.c0000644000175100017510000003430315133003406016471 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include #include #include #include "util.h" #include "openssl-compat.h" #include const char ssh_ca_pvtkey_file[] = "ssh_ca_pvtkey.pem"; const char *key_label = "label"; const uint8_t password[] = "password"; const unsigned char template_dat[] = { // Timestamp key algorithm RSA2048 0x01, 0x00, 0x01, 0x09, // Timestamp public key 0x02, 0x01, 0x00, 0xc2, 0x55, 0x62, 0x08, 0xf5, 0xd2, 0xc2, 0x81, 0xb8, 0xa5, 0x16, 0xfd, 0x27, 0x25, 0xe6, 0x7e, 0x88, 0xcd, 0xc5, 0xd2, 0xcf, 0xdf, 0xd3, 0xea, 0x2d, 0x35, 0xdf, 0x35, 0x27, 0x93, 0x44, 0x45, 0xa6, 0x14, 0x84, 0xee, 0xcb, 0x02, 0xc4, 0x7b, 0x67, 0xc5, 0x94, 0x16, 0xde, 0xe4, 0xa6, 0x1f, 0x25, 0x52, 0x4b, 0x27, 0x9d, 0x4d, 0x09, 0xb1, 0x9b, 0x3e, 0xc5, 0x89, 0xde, 0xe2, 0x90, 0xda, 0xa0, 0x64, 0xc7, 0xb3, 0xaa, 0xae, 0xc7, 0x23, 0x55, 0x37, 0xa0, 0xea, 0x63, 0xb4, 0x1b, 0x65, 0x4a, 0x7f, 0x71, 0xc6, 0x5c, 0xc2, 0x34, 0xfe, 0xa6, 0x02, 0xc9, 0xd6, 0x65, 0x13, 0x5d, 0xca, 0x74, 0x32, 0xf8, 0x7c, 0x01, 0x4b, 0x67, 0x61, 0xdf, 0x27, 0xdd, 0x1d, 0xed, 0x2f, 0x71, 0xcb, 0x8b, 0x23, 0x74, 0x4c, 0xfc, 0x99, 0xe2, 0x23, 0xed, 0xa5, 0xd8, 0x41, 0xe2, 0x9f, 0x82, 0x19, 0xbd, 0xae, 0x50, 0xfb, 0xb9, 0xc7, 0xe6, 0x83, 0x01, 0xac, 0x1c, 0x63, 0x89, 0xb2, 0xac, 0xa7, 0xfd, 0x01, 0x2a, 0xa3, 0xd4, 0x0d, 0x88, 0xf4, 0xcf, 0x9f, 0xed, 0xc1, 0x19, 0xc8, 0x64, 0x71, 0xd3, 0x02, 0x6b, 0x9f, 0x0d, 0xc2, 0xdf, 0x81, 0x5d, 0x53, 0x82, 0x3e, 0xa0, 0xab, 0xf2, 0x93, 0xc9, 0xa4, 0xa8, 0x3b, 0x71, 0xc1, 0xf4, 0xe3, 0x31, 0xa5, 0xdc, 0xfe, 0xc7, 0x9e, 0x7f, 0xd8, 0x2d, 0xd9, 0xfc, 0x90, 0xde, 0xa8, 0xdb, 0x77, 0x0b, 0x2f, 0xb0, 0xf4, 0x49, 0x21, 0x95, 0x95, 0x4b, 0x7e, 0xa0, 0x6f, 0x15, 0x8f, 0x95, 0xdd, 0x72, 0x39, 0x7a, 0x13, 0xb6, 0xcc, 0xfa, 0x9a, 0x07, 0x2d, 0x41, 0xcf, 0x12, 0xaf, 0x8e, 0x87, 0x9f, 0x97, 0xf1, 0x1e, 0x00, 0xac, 0xce, 0x2d, 0x12, 0xd4, 0x34, 0x0c, 0x40, 0x84, 0x33, 0x3a, 0x6c, 0x9f, 0x22, 0x7d, 0x6f, 0x89, 0x87, 0xfb, // CA key allowlist (0x0001, 0x00ab, 0x0014, 0x0005, 0x003a) 0x03, 0x00, 0x0a, 0x00, 0x01, 0x00, 0xab, 0x00, 0x14, 0x00, 0x05, 0x00, 0x3a, // Not before 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, // Not after 0x05, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, // Principals blocklist (root, toor) 0x06, 0x00, 0x0a, 0x72, 0x6f, 0x6f, 0x74, 0x00, 0x74, 0x6f, 0x6f, 0x72, 0x00}; const char ssh_req_file[] = "ssh_req.dat"; const unsigned char expected_result[] = {0x00, 0x00, 0x00, 0x1c, 0x73, 0x73, 0x68, 0x2d, 0x72, 0x73, 0x61, 0x2d, 0x63, 0x65, 0x72, 0x74, 0x2d, 0x76, 0x30, 0x31, 0x40, 0x6f, 0x70, 0x65, 0x6e, 0x73, 0x73, 0x68, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x20, 0x91, 0xe7, 0x84, 0x34, 0x8a, 0xbd, 0x1f, 0x52, 0x2c, 0x4f, 0xa7, 0x59, 0xfb, 0x97, 0xd2, 0x4b, 0x07, 0xbd, 0xad, 0x1f, 0xaf, 0x53, 0x9a, 0x50, 0x35, 0x71, 0xb0, 0x63, 0x64, 0xe2, 0x88, 0xcf, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0xd8, 0x2a, 0x18, 0x56, 0x40, 0x5b, 0xe5, 0xc7, 0xed, 0x94, 0x6f, 0x1f, 0x18, 0x87, 0x33, 0x10, 0xc6, 0xfa, 0x00, 0x1e, 0xdf, 0xf8, 0xf5, 0xaf, 0x89, 0xda, 0x5d, 0x05, 0x39, 0xd2, 0x15, 0x55, 0x78, 0x41, 0xb7, 0x89, 0x51, 0x9c, 0x0b, 0xe0, 0xbc, 0x3c, 0x65, 0x40, 0xdf, 0x84, 0xd2, 0xf1, 0xaf, 0xd8, 0x0f, 0x0b, 0x40, 0x7e, 0x59, 0x84, 0x92, 0x24, 0xa9, 0xaa, 0x83, 0x70, 0x0b, 0x6e, 0x6a, 0xbc, 0xb1, 0x60, 0xbe, 0xa1, 0xad, 0xa1, 0x4f, 0x96, 0xe8, 0xa7, 0xfe, 0xc3, 0x21, 0x41, 0xa7, 0x73, 0xbc, 0x10, 0x0a, 0xdb, 0x4c, 0xfd, 0x7a, 0xef, 0x85, 0xac, 0x99, 0xe7, 0xfb, 0x94, 0x7e, 0x09, 0xb7, 0xb6, 0x8d, 0x5d, 0x03, 0x4b, 0x9c, 0x2e, 0xc6, 0xcc, 0x3b, 0x9c, 0xb3, 0xb2, 0xaf, 0x5d, 0x48, 0xd3, 0x51, 0x33, 0xc2, 0xb8, 0xc2, 0x21, 0x10, 0x40, 0x8e, 0x54, 0x26, 0x2e, 0xbb, 0x32, 0x6e, 0x69, 0x4b, 0x6d, 0xe9, 0x4a, 0xa3, 0x0b, 0xc6, 0xa3, 0x13, 0x1c, 0x72, 0x7d, 0x23, 0x4b, 0x29, 0xe9, 0x3b, 0xfb, 0x26, 0x4e, 0xe2, 0xa4, 0xbc, 0xad, 0xa0, 0x9c, 0xf2, 0xdd, 0xb4, 0x63, 0x21, 0x3b, 0x25, 0xb3, 0xd9, 0x20, 0xb8, 0x62, 0xdb, 0x0c, 0xd3, 0xdc, 0xdf, 0x9f, 0xdf, 0x0e, 0xea, 0x74, 0xd0, 0x3f, 0xb7, 0x04, 0x67, 0xac, 0xb7, 0xea, 0xe2, 0xc9, 0x0c, 0xe2, 0x44, 0x03, 0x3c, 0x6f, 0x9c, 0x56, 0xee, 0x7b, 0x0d, 0x7c, 0xfc, 0xe6, 0x76, 0xac, 0x7b, 0x10, 0x26, 0xf1, 0xb9, 0xaf, 0x53, 0x6c, 0x74, 0xbb, 0x8a, 0x24, 0xd5, 0x91, 0xd8, 0xc8, 0x72, 0xfb, 0x6f, 0x52, 0x58, 0x94, 0xeb, 0x8d, 0xc2, 0x12, 0xbc, 0xd1, 0xde, 0xfb, 0x49, 0xf3, 0x39, 0x51, 0x86, 0xd4, 0x32, 0x9f, 0x36, 0x1b, 0x37, 0xb7, 0x8a, 0x4f, 0x43, 0x7b, 0xd9, 0xf0, 0x26, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x05, 0x75, 0x73, 0x65, 0x72, 0x31, 0x00, 0x00, 0x00, 0x05, 0x75, 0x73, 0x65, 0x72, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x15, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x2d, 0x58, 0x31, 0x31, 0x2d, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2d, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x2d, 0x70, 0x6f, 0x72, 0x74, 0x2d, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x2d, 0x70, 0x74, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x2d, 0x75, 0x73, 0x65, 0x72, 0x2d, 0x72, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x17, 0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x72, 0x73, 0x61, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0xd3, 0x35, 0xad, 0x1a, 0x8a, 0xe2, 0x4d, 0x09, 0xaa, 0xb4, 0x29, 0x8b, 0x1e, 0xbd, 0xc9, 0x41, 0x22, 0xbe, 0x11, 0xd3, 0x0e, 0xab, 0x25, 0xed, 0xbc, 0x5e, 0x2f, 0xaa, 0xf2, 0x48, 0x14, 0x5b, 0x14, 0xee, 0xe3, 0x03, 0x9b, 0xf1, 0x52, 0x87, 0x0d, 0x61, 0x09, 0x51, 0x60, 0xc9, 0x9b, 0xbb, 0x3f, 0xbe, 0xfe, 0x45, 0x46, 0x88, 0x30, 0x05, 0x04, 0x6e, 0xd6, 0x0a, 0x17, 0x8b, 0xd8, 0xbc, 0xf3, 0xf1, 0x50, 0x50, 0xcb, 0xd5, 0x8c, 0x87, 0x17, 0xa5, 0x6c, 0x36, 0xfc, 0x24, 0x30, 0xd0, 0xd2, 0x99, 0x16, 0x72, 0x0f, 0xa9, 0x47, 0xe4, 0x3f, 0xd0, 0x15, 0xc1, 0x86, 0x66, 0xd9, 0xfa, 0x47, 0x3d, 0x52, 0x7c, 0x9b, 0xb2, 0x9e, 0xb4, 0xfe, 0xfd, 0x99, 0x6d, 0x33, 0xf3, 0x6b, 0xa1, 0xd7, 0x5a, 0x21, 0x30, 0x36, 0xdc, 0xd4, 0xa6, 0x26, 0xb2, 0x22, 0xfe, 0x5c, 0x26, 0xe6, 0xfa, 0xee, 0xbc, 0x54, 0x09, 0xec, 0x90, 0xf8, 0xfa, 0xd8, 0x91, 0xf2, 0x22, 0xce, 0xa9, 0x6b, 0x06, 0x5e, 0x55, 0x2d, 0x21, 0x70, 0xed, 0xd3, 0xdb, 0x10, 0xb3, 0xef, 0xc7, 0x09, 0xbc, 0xe2, 0x1d, 0x47, 0xa8, 0x58, 0xff, 0x13, 0x4a, 0x98, 0x4a, 0x7d, 0xce, 0x8b, 0x8c, 0xdb, 0x52, 0xc7, 0xaa, 0x66, 0xca, 0x70, 0xb6, 0xc1, 0x11, 0x7b, 0x2d, 0x87, 0x74, 0x0a, 0x6e, 0xcd, 0xab, 0x41, 0xd0, 0xfb, 0x13, 0xf1, 0xb9, 0xa0, 0x41, 0x59, 0xea, 0x9d, 0x29, 0x42, 0x7b, 0xff, 0x44, 0x6a, 0xb7, 0xbb, 0x26, 0xac, 0x61, 0x9c, 0xa9, 0x6b, 0xb7, 0x3f, 0xdc, 0xb1, 0x73, 0x18, 0x98, 0x56, 0x51, 0x60, 0x65, 0x20, 0x40, 0x51, 0x58, 0xc7, 0x31, 0x86, 0x82, 0x46, 0x25, 0x99, 0x28, 0xfb, 0x3a, 0xc0, 0x34, 0xd8, 0x9c, 0x93, 0x81, 0x13, 0xdb, 0xc5, 0xa8, 0x71, 0xe3, 0x4f, 0xee, 0xe6, 0x9f, 0x00, 0x00, 0x01, 0x0f, 0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x72, 0x73, 0x61, 0x00, 0x00, 0x01, 0x00, 0x0a, 0xcc, 0x96, 0xd1, 0xc3, 0xa5, 0x05, 0xfb, 0x20, 0x2f, 0x3a, 0x70, 0x89, 0x73, 0x42, 0x01, 0x21, 0x14, 0x44, 0xc6, 0x61, 0xbd, 0xc7, 0x5f, 0xf0, 0x8b, 0x04, 0x30, 0xa8, 0x81, 0x81, 0x17, 0x6e, 0x8a, 0xe5, 0x88, 0x2a, 0x4a, 0xf8, 0x58, 0x82, 0x1c, 0x67, 0x18, 0x26, 0x9a, 0x24, 0xb5, 0xf9, 0x1c, 0xc9, 0xe8, 0x12, 0xe2, 0x93, 0xdc, 0x63, 0xc1, 0x4d, 0x39, 0x37, 0x44, 0xb4, 0x06, 0x27, 0x29, 0x53, 0x3b, 0xa1, 0x72, 0xb1, 0xb0, 0x7f, 0xec, 0x76, 0x88, 0x68, 0x54, 0xba, 0xff, 0xe4, 0x29, 0x67, 0xbc, 0xae, 0x0b, 0x33, 0xc3, 0x78, 0xf8, 0x90, 0xe0, 0x33, 0xda, 0x1c, 0x76, 0x5a, 0x18, 0xcf, 0xdf, 0x22, 0x17, 0x7a, 0xba, 0x7d, 0x84, 0x3f, 0xd1, 0x4a, 0x18, 0x6d, 0x67, 0x8c, 0xa0, 0x64, 0xe9, 0x57, 0xdc, 0xb9, 0x99, 0x89, 0x85, 0xd6, 0x28, 0x82, 0x33, 0x3f, 0x95, 0xda, 0xfb, 0x8b, 0x92, 0x35, 0xd2, 0x73, 0x1f, 0xdd, 0x4a, 0x62, 0x0a, 0x67, 0xfb, 0xdc, 0x08, 0x6d, 0x4b, 0xe4, 0xed, 0x9f, 0x22, 0xda, 0xe0, 0x02, 0x8e, 0x8c, 0xcb, 0x33, 0xe6, 0x08, 0x91, 0x4d, 0x26, 0xf3, 0xc7, 0xdd, 0xad, 0x08, 0xec, 0x63, 0xf0, 0xe8, 0x09, 0x14, 0x78, 0xd4, 0xf3, 0xc0, 0xb7, 0xd7, 0x5c, 0x9d, 0x62, 0x00, 0x8c, 0xde, 0xde, 0xcd, 0x75, 0x5c, 0x9b, 0xfb, 0x85, 0xce, 0x3d, 0x58, 0xb0, 0x4a, 0xc8, 0xc3, 0xc5, 0x86, 0xe5, 0x3f, 0xf4, 0x86, 0x29, 0x57, 0x2e, 0x7a, 0xd4, 0x64, 0x29, 0xa8, 0x42, 0xba, 0xf3, 0xb4, 0x92, 0x3f, 0x77, 0xc3, 0x44, 0xaa, 0xcc, 0x30, 0xb8, 0x82, 0xb2, 0xcb, 0x29, 0x9c, 0xea, 0x84, 0xa5, 0x0f, 0x58, 0x59, 0x3d, 0x43, 0xe3, 0xc4, 0xdd, 0x18, 0xdf, 0xe4, 0x82, 0x45, 0x22, 0xea, 0xa7, 0xe2, 0x26, 0xc8, 0x41, 0xfb, 0x37}; int main(void) { yh_connector *connector = NULL; yh_session *session = NULL; yh_rc yrc = YHR_GENERIC_ERROR; uint16_t authkey = 1; const char *connector_url; connector_url = getenv("DEFAULT_CONNECTOR_URL"); if (connector_url == NULL) { connector_url = DEFAULT_CONNECTOR_URL; } yrc = yh_init(); assert(yrc == YHR_SUCCESS); yrc = yh_init_connector(connector_url, &connector); assert(yrc == YHR_SUCCESS); yrc = yh_connect(connector, 0); assert(yrc == YHR_SUCCESS); yrc = yh_create_session_derived(connector, authkey, password, sizeof(password) - 1, false, &session); assert(yrc == YHR_SUCCESS); uint8_t session_id; yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d\n", session_id); FILE *fp = fopen(ssh_ca_pvtkey_file, "rb"); assert(fp != NULL); yh_algorithm algorithm = 0; uint8_t key[2048]; size_t key_material_len = sizeof(key); if (!read_file(fp, key, &key_material_len)) { assert(false); } bool ret = read_private_key(key, key_material_len, &algorithm, key, &key_material_len, false); assert(ret == true); assert(algorithm == YH_ALGO_RSA_2048); yh_capabilities capabilities = {{0}}; yrc = yh_string_to_capabilities("sign-ssh-certificate", &capabilities); assert(yrc == YHR_SUCCESS); uint16_t domain_five = 0; yh_string_to_domains("5", &domain_five); assert(yrc == YHR_SUCCESS); uint16_t ca_key_id = 5; // We use ID 5 because it is in the template's allowlist yrc = yh_util_get_object_info(session, ca_key_id, YH_ASYMMETRIC_KEY, NULL); if (yrc == YHR_SUCCESS) { yrc = yh_util_delete_object(session, ca_key_id, YH_ASYMMETRIC_KEY); assert(yrc == YHR_SUCCESS); } else { assert(yrc == YHR_DEVICE_OBJECT_NOT_FOUND); } yrc = yh_util_import_rsa_key(session, &ca_key_id, key_label, domain_five, &capabilities, algorithm, key, key + (key_material_len / 2)); assert(yrc == YHR_SUCCESS); printf("Key imported with ID %04x\n", ca_key_id); uint16_t template_id = 10; yrc = yh_util_get_object_info(session, template_id, YH_TEMPLATE, NULL); if (yrc == YHR_SUCCESS) { yrc = yh_util_delete_object(session, template_id, YH_TEMPLATE); assert(yrc == YHR_SUCCESS); } else { assert(yrc == YHR_DEVICE_OBJECT_NOT_FOUND); } yrc = yh_util_import_template(session, &template_id, key_label, domain_five, &capabilities, YH_ALGO_TEMPLATE_SSH, template_dat, sizeof(template_dat)); assert(yrc == YHR_SUCCESS); printf("Template imported with ID %04x\n", template_id); uint8_t template2[sizeof(template_dat)]; size_t template2_len = sizeof(template2); yrc = yh_util_get_template(session, template_id, template2, &template2_len); assert(yrc == YHR_SUCCESS); assert(sizeof(template_dat) == template2_len); assert(memcmp(template_dat, template2, template2_len) == 0); uint8_t ssh_req[2048]; size_t ssh_req_len = sizeof(ssh_req); fp = fopen(ssh_req_file, "rb"); assert(fp != NULL); fseek(fp, 0, SEEK_END); ssh_req_len = ftell(fp); assert(ssh_req_len <= sizeof(ssh_req)); fseek(fp, 0, SEEK_SET); size_t read = fread(ssh_req, 1, ssh_req_len, fp); fclose(fp); printf("actually read %zu, expected %zu\n", read, ssh_req_len); assert(read == ssh_req_len); size_t ssh_cert_len = sizeof(ssh_req) - ssh_req_len; yrc = yh_util_sign_ssh_certificate(session, ca_key_id, template_id, YH_ALGO_RSA_PKCS1_SHA1, ssh_req, ssh_req_len, ssh_req + ssh_req_len, &ssh_cert_len); assert(yrc == YHR_SUCCESS); assert(memcmp(expected_result, ssh_req + 4 + 256, sizeof(expected_result)) == 0); BIO *bio; BIO *b64; b64 = BIO_new(BIO_f_base64()); bio = BIO_new_fp(stdout, BIO_NOCLOSE); bio = BIO_push(b64, bio); fprintf(stdout, "ssh-rsa-cert-v01@openssh.com "); BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); assert(BIO_write(bio, ssh_req + 4 + 256, ssh_req_len + ssh_cert_len - 4 - 256) > 0); assert(BIO_flush(bio) == 1); fprintf(stdout, "\n"); BIO_free_all(bio); yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yh_disconnect(connector); assert(yrc == YHR_SUCCESS); yrc = yh_exit(); assert(yrc == YHR_SUCCESS); return 0; } yubihsm-shell-2.7.1/examples/decrypt_ec.c0000644000175100017510000001340615133003406020016 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include #include #include #include #include #include "util.h" #include const char *key_label = "label"; const uint8_t password[] = "password"; int main(void) { yh_connector *connector = NULL; yh_session *session = NULL; yh_rc yrc = YHR_GENERIC_ERROR; uint16_t authkey = 1; const char *connector_url; connector_url = getenv("DEFAULT_CONNECTOR_URL"); if (connector_url == NULL) { connector_url = DEFAULT_CONNECTOR_URL; } yrc = yh_init(); assert(yrc == YHR_SUCCESS); yrc = yh_init_connector(connector_url, &connector); assert(yrc == YHR_SUCCESS); yrc = yh_connect(connector, 0); assert(yrc == YHR_SUCCESS); yrc = yh_create_session_derived(connector, authkey, password, sizeof(password) - 1, false, &session); assert(yrc == YHR_SUCCESS); uint8_t session_id; yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d\n", session_id); yh_capabilities capabilities = {{0}}; yrc = yh_string_to_capabilities("derive-ecdh", &capabilities); assert(yrc == YHR_SUCCESS); uint16_t domain_five = 0; yrc = yh_string_to_domains("5", &domain_five); assert(yrc == YHR_SUCCESS); uint16_t key_id = 0; // ID 0 lets the device generate an ID yrc = yh_util_generate_ec_key(session, &key_id, key_label, domain_five, &capabilities, YH_ALGO_EC_P256); assert(yrc == YHR_SUCCESS); printf("Generated key with ID %04x\n", key_id); uint8_t public_key[512]; size_t public_key_len = sizeof(public_key); yrc = yh_util_get_public_key(session, key_id, public_key, &public_key_len, NULL); assert(yrc == YHR_SUCCESS); printf("Public key (%zd bytes) is:", public_key_len); for (size_t i = 0; i < public_key_len; i++) { printf(" %02x", public_key[i]); } printf("\n"); EC_KEY *eckey = EC_KEY_new(); int nid = algo2nid(YH_ALGO_EC_P256); EC_POINT *point; EC_GROUP *group = EC_GROUP_new_by_curve_name(nid); assert(group != NULL); EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); EC_KEY_set_group(eckey, group); point = EC_POINT_new(group); memmove(public_key + 1, public_key, public_key_len); public_key[0] = 0x04; // hack to make it a valid ec pubkey.. public_key_len++; EC_POINT_oct2point(group, point, public_key, public_key_len, NULL); EC_KEY_set_public_key(eckey, point); // Create the context for parameter generation EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); assert(pctx != NULL); // Initialise the parameter generation assert(EVP_PKEY_paramgen_init(pctx) == 1); // We're going to use the ANSI X9.62 Prime 256v1 curve assert(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_X9_62_prime256v1) == 1); // Create the parameter object params EVP_PKEY *params = NULL; assert(EVP_PKEY_paramgen(pctx, ¶ms) == 1); // Create the context for the key generation EVP_PKEY_CTX *kctx = EVP_PKEY_CTX_new(params, NULL); assert(kctx != NULL); // Generate the key EVP_PKEY *pkey = NULL; assert(EVP_PKEY_keygen_init(kctx) == 1); assert(EVP_PKEY_keygen(kctx, &pkey) == 1); // Get the peer's public key, and provide the peer with our public key EVP_PKEY *peerkey = EVP_PKEY_new(); assert(peerkey != NULL); assert(EVP_PKEY_set1_EC_KEY(peerkey, eckey) == 1); // Create the context for the shared secret derivation EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL); assert(ctx != NULL); // Initialise assert(EVP_PKEY_derive_init(ctx) == 1); // Provide the peer public key assert(EVP_PKEY_derive_set_peer(ctx, peerkey) == 1); uint8_t secret[64]; size_t secret_len = sizeof(secret_len); // Determine buffer length for shared secret assert(EVP_PKEY_derive(ctx, NULL, &secret_len)); // Derive the shared secret assert(EVP_PKEY_derive(ctx, secret, &secret_len) == 1); EC_KEY *eckey2 = EVP_PKEY_get1_EC_KEY(pkey); const EC_POINT *pub = EC_KEY_get0_public_key(eckey2); uint8_t pubkey[128]; size_t pubkey_len = sizeof(pubkey); pubkey_len = EC_POINT_point2oct(group, pub, POINT_CONVERSION_UNCOMPRESSED, pubkey, pubkey_len, NULL); assert(pubkey_len == 65); uint8_t computed_secret[128]; size_t computed_secret_len = sizeof(computed_secret); yrc = yh_util_derive_ecdh(session, key_id, pubkey, pubkey_len, computed_secret, &computed_secret_len); assert(yrc == YHR_SUCCESS); assert(computed_secret_len == secret_len); assert(memcmp(secret, computed_secret, computed_secret_len) == 0); printf("Secrets match\n"); EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(peerkey); EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(kctx); EVP_PKEY_free(params); EVP_PKEY_CTX_free(pctx); EC_POINT_free(point); EC_KEY_free(eckey); EC_KEY_free(eckey2); EC_GROUP_free(group); yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yh_disconnect(connector); assert(yrc == YHR_SUCCESS); yrc = yh_exit(); assert(yrc == YHR_SUCCESS); return 0; } yubihsm-shell-2.7.1/examples/generate_rsa.c0000644000175100017510000001057115133003406020334 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include #include #include #include #include "util.h" #include "openssl-compat.h" #include const char *key_label = "label"; const uint8_t password[] = "password"; const uint8_t data[] = "sudo make me a sandwich"; int main(void) { yh_connector *connector = NULL; yh_session *session = NULL; yh_rc yrc = YHR_GENERIC_ERROR; uint16_t authkey = 1; const char *connector_url; connector_url = getenv("DEFAULT_CONNECTOR_URL"); if (connector_url == NULL) { connector_url = DEFAULT_CONNECTOR_URL; } yrc = yh_init(); assert(yrc == YHR_SUCCESS); yrc = yh_init_connector(connector_url, &connector); assert(yrc == YHR_SUCCESS); yrc = yh_connect(connector, 0); assert(yrc == YHR_SUCCESS); yrc = yh_create_session_derived(connector, authkey, password, sizeof(password) - 1, false, &session); assert(yrc == YHR_SUCCESS); uint8_t session_id; yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d\n", session_id); yh_capabilities capabilities = {{0}}; yrc = yh_string_to_capabilities("sign-pkcs", &capabilities); assert(yrc == YHR_SUCCESS); uint16_t domain_five = 0; yrc = yh_string_to_domains("5", &domain_five); assert(yrc == YHR_SUCCESS); uint16_t key_id = 0; // ID 0 lets the device generate an ID yrc = yh_util_generate_rsa_key(session, &key_id, key_label, domain_five, &capabilities, YH_ALGO_RSA_2048); assert(yrc == YHR_SUCCESS); printf("Generated key with ID %04x\n", key_id); printf("Data to sign (%zu bytes) is: %s\n", sizeof(data) - 1, data); EVP_MD_CTX *mdctx = NULL; uint8_t hashed_data[32]; unsigned int hashed_data_len; mdctx = EVP_MD_CTX_create(); assert(mdctx != NULL); EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL); EVP_DigestUpdate(mdctx, data, sizeof(data) - 1); EVP_DigestFinal_ex(mdctx, hashed_data, &hashed_data_len); EVP_MD_CTX_destroy(mdctx); printf("Hash of data (%d bytes) is:", EVP_MD_size(EVP_sha256())); for (unsigned int i = 0; i < hashed_data_len; i++) { printf(" %02x", hashed_data[i]); } printf("\n"); uint8_t signature[512]; size_t signature_len = sizeof(signature); yrc = yh_util_sign_pkcs1v1_5(session, key_id, true, hashed_data, hashed_data_len, signature, &signature_len); assert(yrc == YHR_SUCCESS); printf("Signature (%zu bytes) is:", signature_len); for (unsigned int i = 0; i < signature_len; i++) { printf(" %02x", signature[i]); } printf("\n"); uint8_t public_key[512]; size_t public_key_len = sizeof(public_key); yrc = yh_util_get_public_key(session, key_id, public_key, &public_key_len, NULL); assert(yrc == YHR_SUCCESS); printf("Public key (%zu bytes) is:", public_key_len); for (unsigned int i = 0; i < public_key_len; i++) { printf(" %02x", public_key[i]); } printf("\n"); BIGNUM *n = BN_bin2bn(public_key, public_key_len, NULL); assert(n != NULL); BIGNUM *e = BN_bin2bn((const unsigned char *) "\x01\x00\x01", 3, NULL); assert(e != NULL); RSA *rsa = RSA_new(); assert(RSA_set0_key(rsa, n, e, NULL) != 0); if (RSA_verify(EVP_MD_type(EVP_sha256()), hashed_data, hashed_data_len, signature, signature_len, rsa) == 1) { printf("Signature successfully verified\n"); } else { printf("Unable to verify signature\n"); } RSA_free(rsa); rsa = NULL; yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yh_disconnect(connector); assert(yrc == YHR_SUCCESS); yrc = yh_exit(); assert(yrc == YHR_SUCCESS); return 0; } yubihsm-shell-2.7.1/examples/import_ec.c0000644000175100017510000001220715133003406017654 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include #include #include #include #include #include #include "util.h" #include const char p256_pvtkey_file[] = "p256_pvtkey.pem"; const char *key_label = "label"; const uint8_t password[] = "password"; const uint8_t data[] = "sudo make me a sandwich"; int main(void) { yh_connector *connector = NULL; yh_session *session = NULL; yh_rc yrc = YHR_GENERIC_ERROR; uint16_t authkey = 1; const char *connector_url; connector_url = getenv("DEFAULT_CONNECTOR_URL"); if (connector_url == NULL) { connector_url = DEFAULT_CONNECTOR_URL; } yrc = yh_init(); assert(yrc == YHR_SUCCESS); yrc = yh_init_connector(connector_url, &connector); assert(yrc == YHR_SUCCESS); yrc = yh_connect(connector, 0); assert(yrc == YHR_SUCCESS); yrc = yh_create_session_derived(connector, authkey, password, sizeof(password) - 1, false, &session); assert(yrc == YHR_SUCCESS); uint8_t session_id; yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d\n", session_id); FILE *fp = fopen(p256_pvtkey_file, "rb"); assert(fp != NULL); yh_algorithm algorithm = 0; uint8_t key[2048]; size_t key_material_len = sizeof(key); if (!read_file(fp, key, &key_material_len)) { assert(false); } bool ret = read_private_key(key, key_material_len, &algorithm, key, &key_material_len, false); assert(ret == true); assert(algorithm == YH_ALGO_EC_P256); yh_capabilities capabilities = {{0}}; yrc = yh_string_to_capabilities("sign-ecdsa", &capabilities); assert(yrc == YHR_SUCCESS); uint16_t domain_five = 0; yrc = yh_string_to_domains("5", &domain_five); assert(yrc == YHR_SUCCESS); uint16_t key_id = 0; // ID 0 lets the device generate an ID yrc = yh_util_import_ec_key(session, &key_id, key_label, domain_five, &capabilities, algorithm, key); assert(yrc == YHR_SUCCESS); printf("Key imported with ID %04x\n", key_id); printf("Data to sign (%zu bytes) is: %s\n", sizeof(data) - 1, data); EVP_MD_CTX *mdctx = NULL; uint8_t hashed_data[32]; unsigned int hashed_data_len; mdctx = EVP_MD_CTX_create(); assert(mdctx != NULL); EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL); EVP_DigestUpdate(mdctx, data, sizeof(data) - 1); EVP_DigestFinal_ex(mdctx, hashed_data, &hashed_data_len); EVP_MD_CTX_destroy(mdctx); printf("Hash of data (%d bytes) is:", EVP_MD_size(EVP_sha256())); for (unsigned int i = 0; i < hashed_data_len; i++) { printf(" %02x", hashed_data[i]); } printf("\n"); uint8_t signature[128]; size_t signature_len = sizeof(signature); yrc = yh_util_sign_ecdsa(session, key_id, hashed_data, hashed_data_len, signature, &signature_len); assert(yrc == YHR_SUCCESS); printf("Signature (%zu bytes) is:", signature_len); for (unsigned int i = 0; i < signature_len; i++) { printf(" %02x", signature[i]); } printf("\n"); uint8_t public_key[512]; size_t public_key_len = sizeof(public_key); yrc = yh_util_get_public_key(session, key_id, public_key, &public_key_len, NULL); assert(yrc == YHR_SUCCESS); printf("Public key (%zu bytes) is:", public_key_len); for (unsigned int i = 0; i < public_key_len; i++) { printf(" %02x", public_key[i]); } printf("\n"); EC_KEY *eckey = EC_KEY_new(); int nid = algo2nid(YH_ALGO_EC_P256); EC_POINT *point; EC_GROUP *group = EC_GROUP_new_by_curve_name(nid); assert(group != NULL); EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); EC_KEY_set_group(eckey, group); point = EC_POINT_new(group); memmove(public_key + 1, public_key, public_key_len); public_key[0] = 0x04; // hack to make it a valid ec pubkey.. public_key_len++; EC_POINT_oct2point(group, point, public_key, public_key_len, NULL); EC_KEY_set_public_key(eckey, point); if (ECDSA_verify(0, hashed_data, hashed_data_len, signature, signature_len, eckey) == 1) { printf("Signature successfully verified\n"); } else { printf("Unable to verify signature\n"); } EC_POINT_free(point); EC_KEY_free(eckey); EC_GROUP_free(group); yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yh_disconnect(connector); assert(yrc == YHR_SUCCESS); yrc = yh_exit(); assert(yrc == YHR_SUCCESS); return 0; } yubihsm-shell-2.7.1/examples/yubico_otp.c0000644000175100017510000002103615133003406020047 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include #include #include #include #include const char *key_label = "label"; const uint8_t password[] = "password"; const uint8_t otp_key[] = {0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f}; static const struct { uint8_t key[16]; uint8_t id[6]; uint16_t use_counter; uint16_t timestamp_low; uint8_t timestamp_high; uint8_t session_counter; uint16_t random; uint16_t crc; uint8_t otp[32]; } test_vectors[] = {{{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}, 0x0001, 0x0001, 0x01, 0x01, 0x0000, 0xfe36, {0x2f, 0x5d, 0x71, 0xa4, 0x91, 0x5d, 0xec, 0x30, 0x4a, 0xa1, 0x3c, 0xcf, 0x97, 0xbb, 0x0d, 0xbb}}, {{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}, 0x0001, 0x0001, 0x01, 0x02, 0x0000, 0x1152, {0xcb, 0x71, 0x0b, 0x46, 0x2b, 0x7b, 0x1c, 0x23, 0x10, 0x0c, 0xb2, 0x46, 0x85, 0xb6, 0x4d, 0x33}}, {{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}, 0x0fff, 0x0001, 0x01, 0x01, 0x0000, 0x9454, {0x77, 0x99, 0x78, 0x12, 0x9b, 0xcc, 0x26, 0x42, 0xc8, 0xad, 0xf5, 0xc1, 0x99, 0x81, 0xa0, 0x16}}, {{0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88}, {0x88, 0x88, 0x88, 0x88, 0x88, 0x88}, 0x8888, 0x8888, 0x88, 0x88, 0x8888, 0xd3b6, {0x20, 0x76, 0x5f, 0xc6, 0x83, 0xe0, 0xfc, 0x7b, 0x62, 0x42, 0x21, 0x86, 0x48, 0x4d, 0x82, 0x37}}, {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0x0000, 0x0000, 0x00, 0x00, 0x0000, 0xa96a, {0x99, 0x9b, 0x08, 0xbf, 0x0b, 0x3b, 0x98, 0xf8, 0x5b, 0x08, 0x76, 0xa8, 0x77, 0x15, 0x16, 0x16}}, {{0xc4, 0x42, 0x28, 0x90, 0x65, 0x30, 0x76, 0xcd, 0xe7, 0x3d, 0x44, 0x9b, 0x19, 0x1b, 0x41, 0x6a}, {0x33, 0xc6, 0x9e, 0x7f, 0x24, 0x9e}, 0x0001, 0x13a7, 0x24, 0x00, 0xc63c, 0x1c86, {0x7e, 0x0f, 0xc9, 0x87, 0x35, 0x16, 0x72, 0xc0, 0x70, 0xfa, 0x5c, 0x05, 0x95, 0xec, 0x68, 0xb8}}}; static uint16_t yubikey_crc16(const uint8_t *buf, size_t buf_size) { uint16_t m_crc = 0xffff; while (buf_size--) { int i, j; m_crc ^= (uint8_t) *buf++ & 0xFF; for (i = 0; i < 8; i++) { j = m_crc & 1; m_crc >>= 1; if (j) { m_crc ^= 0x8408; } } } return m_crc; } int main(void) { yh_connector *connector = NULL; yh_session *session = NULL; yh_rc yrc = YHR_GENERIC_ERROR; uint16_t authkey = 1; const char *connector_url; connector_url = getenv("DEFAULT_CONNECTOR_URL"); if (connector_url == NULL) { connector_url = DEFAULT_CONNECTOR_URL; } yrc = yh_init(); assert(yrc == YHR_SUCCESS); yrc = yh_init_connector(connector_url, &connector); assert(yrc == YHR_SUCCESS); yrc = yh_connect(connector, 0); assert(yrc == YHR_SUCCESS); yrc = yh_create_session_derived(connector, authkey, password, sizeof(password) - 1, false, &session); assert(yrc == YHR_SUCCESS); uint8_t session_id; yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d\n", session_id); yh_capabilities capabilities = {{0}}; yrc = yh_string_to_capabilities("create-otp-aead:decrypt-otp:randomize-otp-aead", &capabilities); assert(yrc == YHR_SUCCESS); uint16_t domain_five = 16; // Domain five is 0b0000000000010000 uint16_t key_id = 0; // ID 0 lets the device generate an ID uint32_t nonce_id = 0x12345678; yrc = yh_util_generate_otp_aead_key(session, &key_id, key_label, domain_five, &capabilities, YH_ALGO_AES128_YUBICO_OTP, nonce_id); assert(yrc == YHR_SUCCESS); printf("Generated OTP key with ID %04x\n", key_id); yrc = yh_util_delete_object(session, key_id, YH_OTP_AEAD_KEY); assert(yrc == YHR_SUCCESS); yrc = yh_util_import_otp_aead_key(session, &key_id, key_label, domain_five, &capabilities, nonce_id, otp_key, sizeof(otp_key)); assert(yrc == YHR_SUCCESS); for (size_t i = 0; i < sizeof(test_vectors) / sizeof(test_vectors[0]); i++) { uint8_t aead[512]; size_t aead_len = sizeof(aead); yrc = yh_util_create_otp_aead(session, key_id, test_vectors[i].key, test_vectors[i].id, aead, &aead_len); assert(yrc == YHR_SUCCESS); uint16_t use_counter; uint16_t timestamp_low; uint8_t timestamp_high; uint8_t session_counter; printf("Checking test vector %zu ... ", i); yrc = yh_util_decrypt_otp(session, key_id, aead, aead_len, test_vectors[i].otp, &use_counter, &session_counter, ×tamp_high, ×tamp_low); assert(yrc == YHR_SUCCESS); assert(test_vectors[i].use_counter == use_counter); assert(test_vectors[i].session_counter == session_counter); assert(test_vectors[i].timestamp_high == timestamp_high); assert(test_vectors[i].timestamp_low == timestamp_low); printf("OK\n"); } printf("Put OTP key with ID %04x\n", key_id); uint8_t otp_data[64]; size_t otp_data_len = sizeof(otp_data); size_t tag_len = 8; size_t nonce_len = 13; uint8_t nonce[13] = {0}; uint8_t out_buf[32]; int out_len; yrc = yh_util_randomize_otp_aead(session, key_id, otp_data, &otp_data_len); assert(yrc == YHR_SUCCESS); EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); // Select cipher assert(EVP_DecryptInit_ex(ctx, EVP_aes_128_ccm(), NULL, NULL, NULL) == 1); // Set nonce length assert(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, nonce_len, NULL) == 1); // Set expected tag value assert(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag_len, otp_data + otp_data_len - tag_len) == 1); // Specify key and IV memcpy(nonce, &nonce_id, 4); memcpy(nonce + 4, otp_data, 6); assert(EVP_DecryptInit_ex(ctx, NULL, NULL, otp_key, nonce) == 1); // Decrypt plaintext, verify tag: can only be called once assert(EVP_DecryptUpdate(ctx, out_buf, &out_len, otp_data + 6, otp_data_len - 6 - tag_len) == 1); EVP_CIPHER_CTX_free(ctx); struct { union { struct { uint8_t id[6]; uint16_t use_counter; uint16_t timestamp_low; uint8_t timestamp_high; uint8_t session_counter; uint16_t rnd; uint16_t crc; }; uint8_t raw[16]; }; } token = {.raw = {0}}; uint8_t otp[16] = {0}; memcpy(token.id, out_buf + 16, 6); token.use_counter = 0xabcd; token.timestamp_low = 0xdcba; token.timestamp_high = 0xff; token.session_counter = 0x00; token.crc = ~yubikey_crc16(token.raw, 14); AES_KEY k; AES_set_encrypt_key(out_buf, 128, &k); AES_ecb_encrypt(token.raw, otp, &k, AES_ENCRYPT); uint16_t use_counter; uint16_t timestamp_low; uint8_t timestamp_high; uint8_t session_counter; yrc = yh_util_decrypt_otp(session, key_id, otp_data, otp_data_len, otp, &use_counter, &session_counter, ×tamp_high, ×tamp_low); assert(yrc == YHR_SUCCESS); assert(use_counter == token.use_counter); assert(timestamp_low == token.timestamp_low); assert(timestamp_high == token.timestamp_high); assert(session_counter == token.session_counter); yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yh_disconnect(connector); assert(yrc == YHR_SUCCESS); yrc = yh_exit(); assert(yrc == YHR_SUCCESS); return 0; } yubihsm-shell-2.7.1/examples/decrypt_rsa.c0000644000175100017510000001172515133003406020216 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include #include #include #include #include #include "util.h" #include #include "openssl-compat.h" const char rsa2048_pvtkey_file[] = "rsa2048_pvtkey.pem"; const char *key_label = "label"; const uint8_t password[] = "password"; const uint8_t data[] = "sudo make me a sandwich"; const uint8_t sha1_empty_string[] = {0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09}; int main(void) { yh_connector *connector = NULL; yh_session *session = NULL; yh_rc yrc = YHR_GENERIC_ERROR; uint16_t authkey = 1; const char *connector_url; connector_url = getenv("DEFAULT_CONNECTOR_URL"); if (connector_url == NULL) { connector_url = DEFAULT_CONNECTOR_URL; } yrc = yh_init(); assert(yrc == YHR_SUCCESS); yrc = yh_init_connector(connector_url, &connector); assert(yrc == YHR_SUCCESS); yrc = yh_connect(connector, 0); assert(yrc == YHR_SUCCESS); yrc = yh_create_session_derived(connector, authkey, password, sizeof(password) - 1, false, &session); assert(yrc == YHR_SUCCESS); uint8_t session_id; yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d\n", session_id); FILE *fp = fopen(rsa2048_pvtkey_file, "rb"); assert(fp != NULL); yh_algorithm algorithm = 0; uint8_t key[2048]; size_t key_material_len = sizeof(key); if (!read_file(fp, key, &key_material_len)) { assert(false); } bool ret2 = read_private_key(key, key_material_len, &algorithm, key, &key_material_len, false); assert(ret2 == true); assert(algorithm == YH_ALGO_RSA_2048); yh_capabilities capabilities = {{0}}; yrc = yh_string_to_capabilities("decrypt-pkcs,decrypt-oaep", &capabilities); assert(yrc == YHR_SUCCESS); uint16_t domain_five = 0; yrc = yh_string_to_domains("5", &domain_five); assert(yrc == YHR_SUCCESS); uint16_t key_id = 0; // ID 0 lets the device generate an ID yrc = yh_util_import_rsa_key(session, &key_id, key_label, domain_five, &capabilities, algorithm, key, key + (key_material_len / 2)); assert(yrc == YHR_SUCCESS); printf("Key imported with ID %04x\n", key_id); uint8_t public_key[512]; size_t public_key_len = sizeof(public_key); yrc = yh_util_get_public_key(session, key_id, public_key, &public_key_len, NULL); assert(yrc == YHR_SUCCESS); printf("Public key (%zu bytes) is:", public_key_len); for (unsigned int i = 0; i < public_key_len; i++) { printf(" %02x", public_key[i]); } printf("\n"); BIGNUM *n = BN_bin2bn(public_key, public_key_len, NULL); assert(n != NULL); BIGNUM *e = BN_bin2bn((const unsigned char *) "\x01\x00\x01", 3, NULL); assert(e != NULL); RSA *rsa = RSA_new(); assert(RSA_set0_key(rsa, n, e, NULL) != 0); uint8_t encrypted[512]; int ret = RSA_public_encrypt(sizeof(data), data, encrypted, rsa, RSA_PKCS1_PADDING); assert(ret == RSA_size(rsa)); uint8_t decrypted[512]; size_t decrypted_len = sizeof(decrypted); yrc = yh_util_decrypt_pkcs1v1_5(session, key_id, encrypted, ret, decrypted, &decrypted_len); assert(yrc == YHR_SUCCESS); assert(memcmp(data, decrypted, decrypted_len) == 0); printf("PKCS1v1.5 decrypted data matches\n"); ret = RSA_public_encrypt(sizeof(data), data, encrypted, rsa, RSA_PKCS1_OAEP_PADDING); assert(ret == RSA_size(rsa)); decrypted_len = sizeof(decrypted); yrc = yh_util_decrypt_oaep(session, key_id, encrypted, ret, decrypted, &decrypted_len, (const uint8_t *) sha1_empty_string, sizeof(sha1_empty_string), YH_ALGO_MGF1_SHA1); assert(yrc == YHR_SUCCESS); assert(memcmp(data, decrypted, decrypted_len) == 0); printf("OAEP decrypted data matches\n"); RSA_free(rsa); rsa = NULL; yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yh_disconnect(connector); assert(yrc == YHR_SUCCESS); yrc = yh_exit(); assert(yrc == YHR_SUCCESS); return 0; } yubihsm-shell-2.7.1/examples/info.c0000644000175100017510000000520615133003406016627 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include int main(void) { yh_connector *connector = NULL; yh_rc yrc = YHR_GENERIC_ERROR; const char *connector_url; connector_url = getenv("DEFAULT_CONNECTOR_URL"); if (connector_url == NULL) { connector_url = DEFAULT_CONNECTOR_URL; } yrc = yh_init(); if (yrc != YHR_SUCCESS) { fprintf(stderr, "unable to initialize yubihsm: %s\n", yh_strerror(yrc)); exit(EXIT_FAILURE); } yrc = yh_init_connector(connector_url, &connector); assert(yrc == YHR_SUCCESS); yrc = yh_connect(connector, 0); assert(yrc == YHR_SUCCESS); char *received_url; yrc = yh_get_connector_address(connector, &received_url); assert(yrc == YHR_SUCCESS); printf("Successfully connected to %s, device is ", received_url); if (yh_connector_has_device(connector) == false) { printf("not present\n"); exit(EXIT_FAILURE); // This won't happen since we manged to connect } printf("present\n"); uint8_t c_major, c_minor, c_patch; yrc = yh_get_connector_version(connector, &c_major, &c_minor, &c_patch); assert(yrc == YHR_SUCCESS); printf("Connector Version: %hhu.%hhu.%hhu\n", c_major, c_minor, c_patch); uint8_t d_major, d_minor, d_patch; uint32_t serial; uint8_t log_total, log_used; yh_algorithm algorithms[YH_MAX_ALGORITHM_COUNT]; size_t n_algorithms = sizeof(algorithms); yrc = yh_util_get_device_info(connector, &d_major, &d_minor, &d_patch, &serial, &log_total, &log_used, algorithms, &n_algorithms); assert(yrc == YHR_SUCCESS); printf("Device Version: %hhu.%hhu.%hhu\n", d_major, d_minor, d_patch); printf("Serial: %d\n", serial); printf("Log: %d/%d (used/total)\n", log_used, log_total); printf("Supported algorithms:\n"); for (size_t i = 0; i < n_algorithms; i++) { const char *str; yh_algo_to_string(algorithms[i], &str); printf("%s\n", str); } yrc = yh_disconnect(connector); assert(yrc == YHR_SUCCESS); yrc = yh_exit(); assert(yrc == YHR_SUCCESS); return 0; } yubihsm-shell-2.7.1/examples/ssh_ca_pvtkey.pem0000644000175100017510000000321715133003406021075 0ustar runnerrunner-----BEGIN RSA PRIVATE KEY----- MIIEpQIBAAKCAQEA0zWtGoriTQmqtCmLHr3JQSK+EdMOqyXtvF4vqvJIFFsU7uMD m/FShw1hCVFgyZu7P77+RUaIMAUEbtYKF4vYvPPxUFDL1YyHF6VsNvwkMNDSmRZy D6lH5D/QFcGGZtn6Rz1SfJuynrT+/ZltM/NroddaITA23NSmJrIi/lwm5vruvFQJ 7JD4+tiR8iLOqWsGXlUtIXDt09sQs+/HCbziHUeoWP8TSphKfc6LjNtSx6pmynC2 wRF7LYd0Cm7Nq0HQ+xPxuaBBWeqdKUJ7/0Rqt7smrGGcqWu3P9yxcxiYVlFgZSBA UVjHMYaCRiWZKPs6wDTYnJOBE9vFqHHjT+7mnwIDAQABAoIBAQCL375WF6grML22 NtUFdNa1plaN42KRgbrhxtZ2taF6qZ9BXWJkgfsPqZKb4yLgIZxuaQRnyIAknQ4E gQeJ9HmDGWK0t+1l7X0B8fGqsG0fTwxJig3bxVXxGTmrTtC9iJoxV7ErCMnQRTmh pVwmzYx4T/BGjnGm6cVnVw3JuimhSVWQnMLUNcwTBQjcwbKI3o/Y4FhoDe0GYof8 6gJq+cj7jFn+x89e1uuXev562CidbOzfGYEc45X+I+DLEN9+xjRPZM0bfnyBS/bM /SCmvcgprITomY+d7H4iJ08BTEEo1z0fWcT8yfM2UgzOrUsjGCOBoZsOnr5zpnlC hfmBc+1BAoGBAOvIt1YN8YpOa/6+y2s8+c95S9yPmdTuO3QanybQMrb1W7iWlOb5 bi3aEuU7cUY+cHbzAYf2WC93pT3cKDPbuvG09EUTXExWw1hOGQ3ot3pgkbshmcBK 8TeQn3kp4d7YM92hnzDLPoEpkWuPdN+If3x2+CQ0Bs8IZjCRJGn5yMAPAoGBAOVR kiLV2qltk5xnOEvlzNXJoaxYeJBiQhXZOrwzYXJXUxz1Kk4QROlSVRboFvHImdGS MoLaUJ5WDE77z77v2f8+zaAeoSakbFaIofJ4qTvXrsc7L4djg9prveQvDZY50mbH SR5la5aQxJkA+TeE1hEowRhNK69aUJIfyfnga+BxAoGBAJG3946IiYm3k8jZs7Av /Be8WCUU3raZEUddGJUNQPqPwsLe1WG2L+DIkLr5NLV761eoMX8MwU18vTPw9yut lejBs+Fo6LcJPCs8AQH2nEZWnlovlu0fo9p6WASy3LQznEJSG6c1RQjgXs5B17I6 kseiYxNE0BxtjXJgkUeppucDAoGAZd5Tlaf8Z9Fmhk8QIh8mXD4i1MXEYRdVFhGW 1u3YNwv1vuJl9aGiiydo5zEYqDWdpwxT5e8Hax78fsW75qzz4UBL5fpVSi42dkZh 8q2JOC061gRDu9gIRaohA9GnLnnnLoMOxzL0lUEgJHvbOb+HvL2m8Z2ub0omipMW jSsVoPECgYEAodn6s+oG9zpq9Gl4Q8jsPiQAgsjwc4CGzz/oBvWooGf8pei0N2gj MIByXmIhpexBlJ4o/MgEMj7g299usGKq06Dg4dMn1DtunkSF/Vd1OcjlZVJpRmrJ m2HWLeo2pjD9W9KaMzZWQ5jxpGliC2TtpWuP44/ihZODFrQZc8DytPo= -----END RSA PRIVATE KEY----- yubihsm-shell-2.7.1/examples/encrypt_aes.c0000644000175100017510000001066615133003406020216 0ustar runnerrunner/* * Copyright 2021 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #undef NDEBUG #include #include #include #include #include #include const char *key_label = "label"; const uint8_t password[] = "password"; const uint8_t plaintext[16] = "singleblock msg"; int main(void) { yh_connector *connector = NULL; yh_session *session = NULL; yh_rc yrc = YHR_GENERIC_ERROR; int r = EXIT_FAILURE; const char *connector_url; connector_url = getenv("DEFAULT_CONNECTOR_URL"); if (connector_url == NULL) { connector_url = DEFAULT_CONNECTOR_URL; } yrc = yh_init(); assert(yrc == YHR_SUCCESS); yrc = yh_init_connector(connector_url, &connector); assert(yrc == YHR_SUCCESS); yrc = yh_connect(connector, 0); assert(yrc == YHR_SUCCESS); yrc = yh_create_session_derived(connector, 1, password, sizeof(password) - 1, false, &session); assert(yrc == YHR_SUCCESS); uint8_t session_id; yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d\n", session_id); yh_algorithm algorithms[YH_MAX_ALGORITHM_COUNT]; size_t algorithm_count = YH_MAX_ALGORITHM_COUNT; yrc = yh_util_get_device_info(connector, NULL, NULL, NULL, NULL, NULL, NULL, algorithms, &algorithm_count); assert(yrc == YHR_SUCCESS); int state = 0; /* unsupported */ for (size_t i = 0; i < algorithm_count; i++) { if (algorithms[i] == YH_ALGO_AES_ECB) { state |= 0x01; } else if (algorithms[i] == YH_ALGO_AES_CBC) { state |= 0x02; } } if (state != 0x03) { fprintf(stderr, "ECB/CBC unsupported or disabled (%#04x)\n", state); r = 64; /* arbitrarily chosen */ goto done; } yh_capabilities capabilities = {{0}}; yrc = yh_string_to_capabilities("encrypt-ecb,decrypt-ecb,encrypt-cbc,decrypt-cbc", &capabilities); assert(yrc == YHR_SUCCESS); uint16_t domain_five = 0; yrc = yh_string_to_domains("5", &domain_five); assert(yrc == YHR_SUCCESS); uint16_t aes_key_id = 0; yrc = yh_util_generate_aes_key(session, &aes_key_id, key_label, domain_five, &capabilities, YH_ALGO_AES256); assert(yrc == YHR_SUCCESS); printf("Generated AES key with ID %04x\n", aes_key_id); uint8_t data[16]; size_t data_len = sizeof(data); yrc = yh_util_encrypt_aes_ecb(session, aes_key_id, plaintext, sizeof(plaintext), data, &data_len); assert(yrc == YHR_SUCCESS); assert(memcmp(data, plaintext, sizeof(plaintext)) != 0); printf("AES-ECB encryption successful\n"); yrc = yh_util_decrypt_aes_ecb(session, aes_key_id, data, data_len, data, &data_len); assert(yrc == YHR_SUCCESS); assert(data_len == sizeof(plaintext)); assert(memcmp(data, plaintext, sizeof(plaintext)) == 0); printf("AES-ECB decryption successful\n"); uint8_t iv[16]; size_t iv_len = sizeof(iv); yrc = yh_util_get_pseudo_random(session, 16, iv, &iv_len); assert(yrc == YHR_SUCCESS); yrc = yh_util_encrypt_aes_cbc(session, aes_key_id, iv, plaintext, sizeof(plaintext), data, &data_len); assert(yrc == YHR_SUCCESS); assert(memcmp(data, plaintext, sizeof(plaintext)) != 0); printf("AES-CBC encryption successful\n"); yrc = yh_util_decrypt_aes_cbc(session, aes_key_id, iv, data, data_len, data, &data_len); assert(yrc == YHR_SUCCESS); assert(data_len == sizeof(plaintext)); assert(memcmp(data, plaintext, sizeof(plaintext)) == 0); printf("AES-CBC decryption successful\n"); r = EXIT_SUCCESS; done: yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yh_disconnect(connector); assert(yrc == YHR_SUCCESS); yrc = yh_exit(); assert(yrc == YHR_SUCCESS); return r; } yubihsm-shell-2.7.1/examples/import_ed.c0000644000175100017510000001130615133003406017654 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include #include #include #include "util.h" #include const char ed25519_pvtkey_file[] = "ed25519_pvtkey.pem"; const char *key_label = "label"; const uint8_t password[] = "password"; const uint8_t data[] = {0x72}; const uint8_t expected_signature[] = {0x92, 0xa0, 0x09, 0xa9, 0xf0, 0xd4, 0xca, 0xb8, 0x72, 0x0e, 0x82, 0x0b, 0x5f, 0x64, 0x25, 0x40, 0xa2, 0xb2, 0x7b, 0x54, 0x16, 0x50, 0x3f, 0x8f, 0xb3, 0x76, 0x22, 0x23, 0xeb, 0xdb, 0x69, 0xda, 0x08, 0x5a, 0xc1, 0xe4, 0x3e, 0x15, 0x99, 0x6e, 0x45, 0x8f, 0x36, 0x13, 0xd0, 0xf1, 0x1d, 0x8c, 0x38, 0x7b, 0x2e, 0xae, 0xb4, 0x30, 0x2a, 0xee, 0xb0, 0x0d, 0x29, 0x16, 0x12, 0xbb, 0x0c, 0x00}; const uint8_t expected_public_key[] = {0x3d, 0x40, 0x17, 0xc3, 0xe8, 0x43, 0x89, 0x5a, 0x92, 0xb7, 0x0a, 0xa7, 0x4d, 0x1b, 0x7e, 0xbc, 0x9c, 0x98, 0x2c, 0xcf, 0x2e, 0xc4, 0x96, 0x8c, 0xc0, 0xcd, 0x55, 0xf1, 0x2a, 0xf4, 0x66, 0x0c}; int main(void) { yh_connector *connector = NULL; yh_session *session = NULL; yh_rc yrc = YHR_GENERIC_ERROR; uint16_t authkey = 1; const char *connector_url; connector_url = getenv("DEFAULT_CONNECTOR_URL"); if (connector_url == NULL) { connector_url = DEFAULT_CONNECTOR_URL; } yrc = yh_init(); assert(yrc == YHR_SUCCESS); yrc = yh_init_connector(connector_url, &connector); assert(yrc == YHR_SUCCESS); yrc = yh_connect(connector, 0); assert(yrc == YHR_SUCCESS); yrc = yh_create_session_derived(connector, authkey, password, sizeof(password) - 1, false, &session); assert(yrc == YHR_SUCCESS); uint8_t session_id; yrc = yh_get_session_id(session, &session_id); assert(yrc == YHR_SUCCESS); printf("Successfully established session %02d\n", session_id); FILE *fp = fopen(ed25519_pvtkey_file, "rb"); assert(fp != NULL); yh_algorithm algorithm = 0; uint8_t key[2048]; size_t key_material_len = sizeof(key); if (!read_file(fp, key, &key_material_len)) { assert(false); } bool ret = read_private_key(key, key_material_len, &algorithm, key, &key_material_len, false); assert(ret == true); assert(algorithm == YH_ALGO_EC_ED25519); yh_capabilities capabilities = {{0}}; yrc = yh_string_to_capabilities("sign-eddsa", &capabilities); assert(yrc == YHR_SUCCESS); uint16_t domain_five = 0; yrc = yh_string_to_domains("5", &domain_five); assert(yrc == YHR_SUCCESS); uint16_t key_id = 0; // ID 0 lets the device generate an ID yrc = yh_util_import_ed_key(session, &key_id, key_label, domain_five, &capabilities, algorithm, key); assert(yrc == YHR_SUCCESS); printf("Key imported with ID %04x\n", key_id); printf("Signing %zu bytes of data\n", sizeof(data)); uint8_t signature[128]; size_t signature_len = sizeof(signature); yrc = yh_util_sign_eddsa(session, key_id, data, sizeof(data), signature, &signature_len); assert(yrc == YHR_SUCCESS); printf("Signature (%zu bytes) is:", signature_len); for (unsigned int i = 0; i < signature_len; i++) { printf(" %02x", signature[i]); } printf("\n"); assert(signature_len == 64); assert(memcmp(signature, expected_signature, 64) == 0); uint8_t public_key[512]; size_t public_key_len = sizeof(public_key); yrc = yh_util_get_public_key(session, key_id, public_key, &public_key_len, NULL); assert(yrc == YHR_SUCCESS); assert(public_key_len == 32); assert(memcmp(public_key, expected_public_key, 32) == 0); printf("Public key (%zu bytes) is:", public_key_len); for (unsigned int i = 0; i < public_key_len; i++) { printf(" %02x", public_key[i]); } printf("\n"); yrc = yh_util_close_session(session); assert(yrc == YHR_SUCCESS); yrc = yh_destroy_session(&session); assert(yrc == YHR_SUCCESS); yh_disconnect(connector); assert(yrc == YHR_SUCCESS); yrc = yh_exit(); assert(yrc == YHR_SUCCESS); return 0; } yubihsm-shell-2.7.1/LICENSE0000644000175100017510000002205615133003406014721 0ustar runnerrunnerApache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: You must give any other recipients of the Work or Derivative Works a copy of this License; and You must cause any modified files to carry prominent notices stating that You changed the files; and You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS yubihsm-shell-2.7.1/yhwrap/0000755000175100017510000000000015133003464015225 5ustar runnerrunneryubihsm-shell-2.7.1/yhwrap/cmdline.h0000644000175100017510000002143015133003464017011 0ustar runnerrunner/** @file cmdline.h * @brief The header file for the command line option parser * generated by GNU Gengetopt version 2.23 * http://www.gnu.org/software/gengetopt. * DO NOT modify this file, since it can be overwritten * @author GNU Gengetopt */ #ifndef CMDLINE_H #define CMDLINE_H /* If we use autoconf. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include /* for FILE */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #ifndef CMDLINE_PARSER_PACKAGE /** @brief the program name (used for printing errors) */ #define CMDLINE_PARSER_PACKAGE PACKAGE #endif #ifndef CMDLINE_PARSER_PACKAGE_NAME /** @brief the complete program name (used for help and version) */ #ifdef PACKAGE_NAME #define CMDLINE_PARSER_PACKAGE_NAME PACKAGE_NAME #else #define CMDLINE_PARSER_PACKAGE_NAME PACKAGE #endif #endif #ifndef CMDLINE_PARSER_VERSION /** @brief the program version */ #define CMDLINE_PARSER_VERSION VERSION #endif /** @brief Where the command line options are stored */ struct gengetopt_args_info { const char *help_help; /**< @brief Print help and exit help description. */ const char *version_help; /**< @brief Print version and exit help description. */ char * algorithm_arg; /**< @brief Object algorithm. */ char * algorithm_orig; /**< @brief Object algorithm original value given at command line. */ const char *algorithm_help; /**< @brief Object algorithm help description. */ char * capabilities_arg; /**< @brief Object capabilities. */ char * capabilities_orig; /**< @brief Object capabilities original value given at command line. */ const char *capabilities_help; /**< @brief Object capabilities help description. */ char * delegated_arg; /**< @brief Object delegates capabilities. */ char * delegated_orig; /**< @brief Object delegates capabilities original value given at command line. */ const char *delegated_help; /**< @brief Object delegates capabilities help description. */ char * domains_arg; /**< @brief Object domains. */ char * domains_orig; /**< @brief Object domains original value given at command line. */ const char *domains_help; /**< @brief Object domains help description. */ short id_arg; /**< @brief Object ID (default='0'). */ char * id_orig; /**< @brief Object ID original value given at command line. */ const char *id_help; /**< @brief Object ID help description. */ char * in_arg; /**< @brief Input data (filename). */ char * in_orig; /**< @brief Input data (filename) original value given at command line. */ const char *in_help; /**< @brief Input data (filename) help description. */ char * out_arg; /**< @brief Output data (filename). */ char * out_orig; /**< @brief Output data (filename) original value given at command line. */ const char *out_help; /**< @brief Output data (filename) help description. */ char * label_arg; /**< @brief Object label. */ char * label_orig; /**< @brief Object label original value given at command line. */ const char *label_help; /**< @brief Object label help description. */ char * wrapkey_arg; /**< @brief Key to wrap data with (filename). */ char * wrapkey_orig; /**< @brief Key to wrap data with (filename) original value given at command line. */ const char *wrapkey_help; /**< @brief Key to wrap data with (filename) help description. */ unsigned int help_given ; /**< @brief Whether help was given. */ unsigned int version_given ; /**< @brief Whether version was given. */ unsigned int algorithm_given ; /**< @brief Whether algorithm was given. */ unsigned int capabilities_given ; /**< @brief Whether capabilities was given. */ unsigned int delegated_given ; /**< @brief Whether delegated was given. */ unsigned int domains_given ; /**< @brief Whether domains was given. */ unsigned int id_given ; /**< @brief Whether id was given. */ unsigned int in_given ; /**< @brief Whether in was given. */ unsigned int out_given ; /**< @brief Whether out was given. */ unsigned int label_given ; /**< @brief Whether label was given. */ unsigned int wrapkey_given ; /**< @brief Whether wrapkey was given. */ } ; /** @brief The additional parameters to pass to parser functions */ struct cmdline_parser_params { int override; /**< @brief whether to override possibly already present options (default 0) */ int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */ int check_required; /**< @brief whether to check that all required options were provided (default 1) */ int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */ int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */ } ; /** @brief the purpose string of the program */ extern const char *gengetopt_args_info_purpose; /** @brief the usage string of the program */ extern const char *gengetopt_args_info_usage; /** @brief the description string of the program */ extern const char *gengetopt_args_info_description; /** @brief all the lines making the help output */ extern const char *gengetopt_args_info_help[]; /** * The command line parser * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info); /** * The command line parser (version with additional parameters - deprecated) * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @param override whether to override possibly already present options * @param initialize whether to initialize the option structure my_args_info * @param check_required whether to check that all required options were provided * @return 0 if everything went fine, NON 0 if an error took place * @deprecated use cmdline_parser_ext() instead */ int cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required); /** * The command line parser (version with additional parameters) * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @param params additional parameters for the parser * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params); /** * Save the contents of the option struct into an already open FILE stream. * @param outfile the stream where to dump options * @param args_info the option struct to dump * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info); /** * Save the contents of the option struct into a (text) file. * This file can be read by the config file parser (if generated by gengetopt) * @param filename the file where to save * @param args_info the option struct to save * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info); /** * Print the help */ void cmdline_parser_print_help(void); /** * Print the version */ void cmdline_parser_print_version(void); /** * Initializes all the fields a cmdline_parser_params structure * to their default values * @param params the structure to initialize */ void cmdline_parser_params_init(struct cmdline_parser_params *params); /** * Allocates dynamically a cmdline_parser_params structure and initializes * all its fields to their default values * @return the created and initialized cmdline_parser_params structure */ struct cmdline_parser_params *cmdline_parser_params_create(void); /** * Initializes the passed gengetopt_args_info structure's fields * (also set default values for options that have a default) * @param args_info the structure to initialize */ void cmdline_parser_init (struct gengetopt_args_info *args_info); /** * Deallocates the string fields of the gengetopt_args_info structure * (but does not deallocate the structure itself) * @param args_info the structure to deallocate */ void cmdline_parser_free (struct gengetopt_args_info *args_info); /** * Checks that all the required options were specified * @param args_info the structure to check * @param prog_name the name of the program that will be used to print * possible errors * @return */ int cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* CMDLINE_H */ yubihsm-shell-2.7.1/yhwrap/README.adoc0000644000175100017510000000472415133003406017015 0ustar runnerrunner== YubiHSM Wrap YubiHSM Wrap is a command-line tool to create "offline wraps" for a YubiHSM 2 device. One of the functionalities supported by the YubiHSM is to import objects under wrap. The typical use is to generate an object on one device, export it under wrap using a Wrap Key and import it to a different device which has the same Wrap Key. At times it is also useful to be able to create those wrapped objects from a computer, so that they can be encrypted at rest and also easily sent to devices for use. === Example This example shows how to generate a private key using OpenSSL, wrap it to a pre-shared Wrap Key and import it on a device. The first thing we need is a Wrap Key that we will use to wrap the object. For this example we are going to use `00112233445566778899aabbccddeeff` We first save it to a file called `wrap.key` by running [source, bash] ---- $ echo -en '\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff' >wrap.key ---- The Wrap Key has to also exist on the YubiHSM. We can import it in the device and give it Object ID `20` by running [source, bash] ---- $ yubihsm-shell -p password -a put-wrap-key -i 20 -c all --delegated all --informat bin --in wrap.key ---- At this point we can use OpenSSL to generate the RSA key that we would like to wrap and import [source, bash] ---- $ openssl genrsa -out private.pem ---- We can now use `yubihsm-wrap` to produce the wrapped version of the private key. Specifically, we will be asking for the key to have, once imported, Object ID `30`, label `RSA_Key` and belong to Domains `1`, `2` and `5`. [source, bash] ---- $ yubihsm-wrap -a rsa2048 -c sign-pkcs -d 1,2,5 --id 30 --label RSA_Key --in private.pem --wrapkey wrap.key --out private.yhw ---- The output file `private.yhw` is the wrapped version of the key and it is ready to be imported in the device using the Wrap Key that we stored before. The command to do that is [source, bash] ---- $ yubihsm-shell -p password -a put-wrapped --wrap-id 20 --in private.yhw ---- We should now be able to retrieve information about the Asymmetric Key with Object ID `30` by running [source, bash] ---- $ yubihsm-shell -p password -a get-object-info -i 30 -t asymmetric-key Using default connector URL: http://localhost:12345 Session keepalive set up to run every 15 seconds Created session 0 id: 0x001e, type: asymmetric-key, algorithm: rsa2048, label: "RSA_Key", length: 896, domains: 1:2:5, sequence: 0, origin: imported:imported_wrapped, capabilities: sign-pkcs ---- yubihsm-shell-2.7.1/yhwrap/version.rc.in0000644000175100017510000000214515133003406017643 0ustar runnerrunner #include #define VER_FILEVERSION @yubihsm_shell_VERSION_MAJOR@,@yubihsm_shell_VERSION_MINOR@,@yubihsm_shell_VERSION_PATCH@,0 #define VER_FILEVERSION_STR "@yubihsm_shell_VERSION_MAJOR@.@yubihsm_shell_VERSION_MINOR@.@yubihsm_shell_VERSION_PATCH@.0" VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION PRODUCTVERSION VER_FILEVERSION FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x40004L FILETYPE 0x2L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Yubico AB" VALUE "FileDescription", "YubiHSM Wrap" VALUE "FileVersion", VER_FILEVERSION_STR VALUE "InternalName", "yubihsm-wrap.exe" VALUE "LegalCopyright", "\xa9 Yubico AB" VALUE "OriginalFilename", "yubihsm-wrap.exe" VALUE "ProductName", "YubiHSM" VALUE "ProductVersion", VER_FILEVERSION_STR END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END yubihsm-shell-2.7.1/yhwrap/CMakeLists.txt0000644000175100017510000000476515133003406017775 0ustar runnerrunner# # Copyright 2015-2018 Yubico AB # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # include(${CMAKE_SOURCE_DIR}/cmake/openssl.cmake) find_libcrypto() set ( SOURCE ../common/hash.c ../common/parsing.c ../common/pkcs5.c ../common/util.c ../common/openssl-compat.c main.c ) if(WIN32) set(SOURCE ${SOURCE} cmdline.c) include(${CMAKE_SOURCE_DIR}/cmake/getopt.cmake) find_getopt() else(WIN32) include(gengetopt) add_gengetopt_files (cmdline) set(SOURCE ${SOURCE} ${GGO_C}) message("${GGO_C}") endif(WIN32) include_directories ( ${LIBCRYPTO_INCLUDEDIR} ${CMAKE_CURRENT_SOURCE_DIR}/../lib ${CMAKE_CURRENT_SOURCE_DIR}/../common ) if(${WIN32}) list(APPEND SOURCE ${CMAKE_CURRENT_BINARY_DIR}/version.rc) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY) endif(${WIN32}) # NOTE(adma): required by gengetopt add_definitions (-DPACKAGE="yubihsm-wrap") add_definitions (-DVERSION="${yubihsm_shell_VERSION_MAJOR}.${yubihsm_shell_VERSION_MINOR}.${yubihsm_shell_VERSION_PATCH}") list(APPEND LCOV_REMOVE_PATTERNS "'${PROJECT_SOURCE_DIR}/yhwrap/cmdline.c'") if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") set_property(SOURCE ${GGO_C} APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-unused-but-set-variable ") endif() add_executable (yubihsm-wrap ${SOURCE}) target_link_libraries ( yubihsm-wrap ${LIBCRYPTO_LDFLAGS} ${GETOPT_LIBS} yubihsm ) set_target_properties(yubihsm-wrap PROPERTIES INSTALL_RPATH "${YUBIHSM_INSTALL_LIB_DIR}") add_coverage(yubihsm-wrap) install( TARGETS yubihsm-wrap ARCHIVE DESTINATION "${YUBIHSM_INSTALL_LIB_DIR}" LIBRARY DESTINATION "${YUBIHSM_INSTALL_LIB_DIR}" RUNTIME DESTINATION "${YUBIHSM_INSTALL_BIN_DIR}") if (NOT WITHOUT_MANPAGES) include (help2man) add_help2man_manpage (yubihsm-wrap.1 yubihsm-wrap) add_custom_target (yubihsm-wrap-man ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/yubihsm-wrap.1 ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/yubihsm-wrap.1" DESTINATION "${YUBIHSM_INSTALL_MAN_DIR}/man1") endif () yubihsm-shell-2.7.1/yhwrap/main.c0000644000175100017510000002777115133003406016327 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include "../common/platform-config.h" #ifdef __WIN32 #include #else #include #endif #include #include #include "cmdline.h" #include "parsing.h" #include "pkcs5.h" #include "util.h" #include #define INPUT_BUFSIZE 4096 #define WRAPKEY_BUFSIZE 32 #define OBJECT_HEADER_SIZE 59 static bool wrap_data(uint8_t *key, size_t key_len, uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len) { EVP_CIPHER_CTX *ctx = NULL; const EVP_CIPHER *cipher_type; uint8_t nonce[13]; int nonce_len = 13; int tag_len = 16; int len; ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) { return false; } switch (key_len) { case 16: cipher_type = EVP_aes_128_ccm(); break; case 24: cipher_type = EVP_aes_192_ccm(); break; case 32: cipher_type = EVP_aes_256_ccm(); break; default: return false; } if (RAND_bytes(nonce, nonce_len) != 1) { return false; } memcpy(out, nonce, nonce_len); // Select cipher if (EVP_EncryptInit_ex(ctx, cipher_type, NULL, NULL, NULL) != 1) { return false; } // Set nonce length if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, nonce_len, NULL) != 1) { return false; } // Set tag length if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag_len, NULL) != 1) { return false; } // Initialize key and IV if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce) != 1) { return false; } // Provide the total plaintext length if (EVP_EncryptUpdate(ctx, NULL, &len, NULL, in_len) != 1) { return false; } // Provide the message to be encrypted, and obtain the encrypted output if (EVP_EncryptUpdate(ctx, out + nonce_len, &len, in, in_len) != 1) { return false; } *out_len = len; // Finalize the encryption if (EVP_EncryptFinal_ex(ctx, out + nonce_len + *out_len, &len) != 1) { return false; } *out_len += len; // Get the tag if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_GET_TAG, tag_len, out + nonce_len + *out_len) != 1) { return false; } *out_len += tag_len; *out_len += nonce_len; // Clean up EVP_CIPHER_CTX_free(ctx); return true; } static void format_header(yh_algorithm wrapkey_algorithm, yh_capabilities capabilities, uint16_t id, uint16_t data_len, uint16_t domains, yh_object_type type, yh_algorithm algorithm, uint8_t *label, uint8_t *header) { *header = (uint8_t) wrapkey_algorithm; header++; memcpy(header, capabilities.capabilities, YH_CAPABILITIES_LEN); header += YH_CAPABILITIES_LEN; *((uint16_t *) header) = htons(id); header += sizeof(uint16_t); *((uint16_t *) header) = htons(data_len); header += sizeof(uint16_t); *((uint16_t *) header) = htons(domains); header += sizeof(uint16_t); *header = (uint8_t) type; header++; *header = (uint8_t) algorithm; header++; *header = 0x00; // Sequence header++; *header = 0x02; // Origin header++; memcpy(header, label, YH_OBJ_LABEL_LEN); header += YH_OBJ_LABEL_LEN; } static FILE *open_file(const char *name, bool input) { if (input) { if (strcmp(name, "-") == 0) { return stdin; } else { return fopen(name, "rb"); } } else { if (strcmp(name, "-") == 0) { return stdout; } else { return fopen(name, "wb"); } } } static void dump_hex(const unsigned char *buf, unsigned int len) { unsigned int i; for (i = 0; i < len; i++) { if (i && !(i % 32)) fprintf(stderr, "\n"); else if (i && !(i % 8)) fprintf(stderr, " "); fprintf(stderr, "%02x", buf[i]); } fprintf(stderr, "\n"); } int main(int argc, char *argv[]) { struct gengetopt_args_info args_info; int rc = EXIT_FAILURE; yh_rc yhrc; FILE *input_file = NULL; FILE *output_file = NULL; FILE *wrapkey_file = NULL; #pragma pack(push, 1) union { struct { uint8_t header[OBJECT_HEADER_SIZE]; uint8_t body[INPUT_BUFSIZE]; }; uint8_t buf[1]; } wrap_object = {{{0}, {0}}}; #pragma pack(pop) size_t wrap_object_len = sizeof(wrap_object.body); if (cmdline_parser(argc, argv, &args_info) != 0) { goto main_exit; } yh_algorithm algorithm; yhrc = yh_string_to_algo(args_info.algorithm_arg, &algorithm); if (yhrc != YHR_SUCCESS) { fprintf(stderr, "Unable to parse algorithm: %s\n", yh_strerror(yhrc)); goto main_exit; } yh_capabilities capabilities = {{0}}; yhrc = yh_string_to_capabilities(args_info.capabilities_arg, &capabilities); if (yhrc != YHR_SUCCESS) { fprintf(stderr, "Unable to parse capabilities: %s\n", yh_strerror(yhrc)); goto main_exit; } uint16_t domains; yhrc = yh_string_to_domains(args_info.domains_arg, &domains); if (yhrc != YHR_SUCCESS) { fprintf(stderr, "Unable to parse domains: %s\n", yh_strerror(yhrc)); goto main_exit; } uint16_t id = args_info.id_arg; uint8_t label[YH_OBJ_LABEL_LEN] = {0}; size_t label_len = strlen(args_info.label_arg); if (label_len > YH_OBJ_LABEL_LEN) { fprintf(stderr, "Unable to parse label: label too long, maximum length is %d\n", YH_OBJ_LABEL_LEN); goto main_exit; } memcpy(label, args_info.label_arg, label_len); yh_object_type type; if (algo2type(algorithm, &type) == false) { fprintf(stderr, "Invalid algorithm\n"); goto main_exit; } yh_capabilities delegated = {{0}}; bool has_delegated = ((type == YH_AUTHENTICATION_KEY || type == YH_WRAP_KEY) ? true : false); if (has_delegated == true) { if (!args_info.delegated_given) { fprintf(stderr, "Missing delegated capabilities argument\n"); goto main_exit; } yhrc = yh_string_to_capabilities(args_info.delegated_arg, &delegated); if (yhrc != YHR_SUCCESS) { fprintf(stderr, "Unable to parse delegated capabilities: %s\n", yh_strerror(yhrc)); goto main_exit; } } input_file = open_file(args_info.in_arg, true); if (input_file == NULL) { perror("Unable to open input file"); goto main_exit; } switch (type) { case YH_AUTHENTICATION_KEY: { char password[256] = {0}; size_t password_len = sizeof(password); if (input_file == stdin) { const char *prompt = "Derivation Password: "; if (EVP_read_pw_string(password, password_len - 1, prompt, 1)) { fprintf(stderr, "Unable to read password prompt\n"); goto main_exit; } password_len = strlen(password); } else { if (read_file(input_file, (uint8_t *) password, &password_len) == false) { fprintf(stderr, "Unable to read input file\n"); goto main_exit; } if (password[password_len - 1] == '\n') { password_len--; } if (password[password_len - 1] == '\r') { password_len--; } password[password_len] = '\0'; } uint8_t key[YH_KEY_LEN * 2]; bool ret = pkcs5_pbkdf2_hmac((const uint8_t *) password, password_len, (const uint8_t *) YH_DEFAULT_SALT, strlen(YH_DEFAULT_SALT), YH_DEFAULT_ITERS, _SHA256, key, sizeof(key)); if (ret == false) { fprintf(stderr, "Unable to derive keys\n"); goto main_exit; } memcpy(wrap_object.body, delegated.capabilities, YH_CAPABILITIES_LEN); wrap_object_len -= YH_CAPABILITIES_LEN; memcpy(wrap_object.body + YH_CAPABILITIES_LEN, key, YH_KEY_LEN); memcpy(wrap_object.body + YH_CAPABILITIES_LEN + YH_KEY_LEN, key + YH_KEY_LEN, YH_KEY_LEN); wrap_object_len = YH_CAPABILITIES_LEN + YH_KEY_LEN * 2; } break; case YH_WRAP_KEY: { memcpy(wrap_object.body, delegated.capabilities, YH_CAPABILITIES_LEN); wrap_object_len -= YH_CAPABILITIES_LEN; if (read_file(input_file, wrap_object.body + YH_CAPABILITIES_LEN, &wrap_object_len) == false) { fprintf(stderr, "Unable to read input file\n"); goto main_exit; } wrap_object_len += YH_CAPABILITIES_LEN; } break; case YH_ASYMMETRIC_KEY: { yh_algorithm parsed_algorithm; if (read_file(input_file, wrap_object.body, &wrap_object_len) == false) { fprintf(stderr, "Unable to read input file\n"); goto main_exit; } if (read_private_key(wrap_object.body, wrap_object_len, &parsed_algorithm, wrap_object.body, &wrap_object_len, true) != true) { fprintf(stderr, "Unable to read asymmetric private key\n"); goto main_exit; } if (parsed_algorithm != algorithm) { fprintf(stderr, "Mismatched algorithm\n"); goto main_exit; } } break; case YH_HMAC_KEY: { if (read_file(input_file, wrap_object.body, &wrap_object_len) == false) { fprintf(stderr, "Unable to read input file\n"); goto main_exit; } if (split_hmac_key(algorithm, wrap_object.body, wrap_object_len, wrap_object.body, &wrap_object_len) != true) { fprintf(stderr, "Unable to format hmac key\n"); goto main_exit; } } break; default: if (read_file(input_file, wrap_object.body, &wrap_object_len) == false) { fprintf(stderr, "Unable to read input file\n"); goto main_exit; } } wrapkey_file = open_file(args_info.wrapkey_arg, true); if (wrapkey_file == NULL) { perror("Unable to open wrapkey file"); goto main_exit; } uint8_t wrapkey_buf[WRAPKEY_BUFSIZE]; size_t wrapkey_buf_len = sizeof(wrapkey_buf); if (read_file(wrapkey_file, wrapkey_buf, &wrapkey_buf_len) == false) { fprintf(stderr, "Unable to read wrapkey file\n"); } yh_algorithm wrapkey_algorithm; switch (wrapkey_buf_len) { case 16: wrapkey_algorithm = YH_ALGO_AES128_CCM_WRAP; break; case 24: wrapkey_algorithm = YH_ALGO_AES192_CCM_WRAP; break; case 32: wrapkey_algorithm = YH_ALGO_AES256_CCM_WRAP; break; default: fprintf(stderr, "Unable to parse wrapkey: invalid length\n"); goto main_exit; } output_file = open_file(args_info.out_arg, false); if (output_file == NULL) { perror("Unable to open output file"); goto main_exit; } format_header(wrapkey_algorithm, capabilities, id, wrap_object_len, domains, type, algorithm, label, wrap_object.header); uint8_t wrapped[2048] = {0}; size_t wrapped_len = sizeof(wrapped); if (wrap_data(wrapkey_buf, wrapkey_buf_len, wrap_object.buf, OBJECT_HEADER_SIZE + wrap_object_len, wrapped, &wrapped_len) == false) { fprintf(stderr, "Unable to wrap data\n"); goto main_exit; } if (getenv("DEBUG") != NULL) { dump_hex(wrap_object.buf, OBJECT_HEADER_SIZE + wrap_object_len); } if (write_file(wrapped, wrapped_len, output_file, _base64) == false || write_file((uint8_t *) "\n", 1, output_file, _binary) == false) { fprintf(stderr, "Unable to write output file\n"); goto main_exit; } rc = EXIT_SUCCESS; main_exit: cmdline_parser_free(&args_info); if (input_file != NULL) { fclose(input_file); input_file = NULL; } if (output_file != NULL) { fclose(output_file); output_file = NULL; } if (wrapkey_file != NULL) { fclose(wrapkey_file); wrapkey_file = NULL; } return rc; } yubihsm-shell-2.7.1/yhwrap/cmdline.ggo0000644000175100017510000000201415133003406017327 0ustar runnerrunner# # Copyright 2015-2018 Yubico AB # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # option "algorithm" a "Object algorithm" string option "capabilities" c "Object capabilities" string option "delegated" e "Object delegates capabilities" string optional option "domains" d "Object domains" string option "id" i "Object ID" short optional default="0" option "in" - "Input data (filename)" string option "out" - "Output data (filename)" string option "label" l "Object label" string option "wrapkey" k "Key to wrap data with (filename)" string yubihsm-shell-2.7.1/yhwrap/cmdline.c0000644000175100017510000005351315133003464017013 0ustar runnerrunner/* File autogenerated by gengetopt version 2.23 generated with the following command: gengetopt -i /home/runner/work/yubihsm-shell/yubihsm-shell/yhwrap/cmdline.ggo --output-dir /home/runner/work/yubihsm-shell/yubihsm-shell/yhwrap cmdline The developers of gengetopt consider the fixed text that goes in all gengetopt output files to be in the public domain: we make no copyright claims on it. */ /* If we use autoconf. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #ifndef FIX_UNUSED #define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */ #endif #include #include "cmdline.h" const char *gengetopt_args_info_purpose = ""; const char *gengetopt_args_info_usage = "Usage: " CMDLINE_PARSER_PACKAGE " [OPTION]..."; const char *gengetopt_args_info_versiontext = ""; const char *gengetopt_args_info_description = ""; const char *gengetopt_args_info_help[] = { " -h, --help Print help and exit", " -V, --version Print version and exit", " -a, --algorithm=STRING Object algorithm", " -c, --capabilities=STRING Object capabilities", " -e, --delegated=STRING Object delegates capabilities", " -d, --domains=STRING Object domains", " -i, --id=SHORT Object ID (default=`0')", " --in=STRING Input data (filename)", " --out=STRING Output data (filename)", " -l, --label=STRING Object label", " -k, --wrapkey=STRING Key to wrap data with (filename)", 0 }; typedef enum {ARG_NO , ARG_STRING , ARG_SHORT } cmdline_parser_arg_type; static void clear_given (struct gengetopt_args_info *args_info); static void clear_args (struct gengetopt_args_info *args_info); static int cmdline_parser_internal (int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params, const char *additional_error); static int cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error); static char * gengetopt_strdup (const char *s); static void clear_given (struct gengetopt_args_info *args_info) { args_info->help_given = 0 ; args_info->version_given = 0 ; args_info->algorithm_given = 0 ; args_info->capabilities_given = 0 ; args_info->delegated_given = 0 ; args_info->domains_given = 0 ; args_info->id_given = 0 ; args_info->in_given = 0 ; args_info->out_given = 0 ; args_info->label_given = 0 ; args_info->wrapkey_given = 0 ; } static void clear_args (struct gengetopt_args_info *args_info) { FIX_UNUSED (args_info); args_info->algorithm_arg = NULL; args_info->algorithm_orig = NULL; args_info->capabilities_arg = NULL; args_info->capabilities_orig = NULL; args_info->delegated_arg = NULL; args_info->delegated_orig = NULL; args_info->domains_arg = NULL; args_info->domains_orig = NULL; args_info->id_arg = 0; args_info->id_orig = NULL; args_info->in_arg = NULL; args_info->in_orig = NULL; args_info->out_arg = NULL; args_info->out_orig = NULL; args_info->label_arg = NULL; args_info->label_orig = NULL; args_info->wrapkey_arg = NULL; args_info->wrapkey_orig = NULL; } static void init_args_info(struct gengetopt_args_info *args_info) { args_info->help_help = gengetopt_args_info_help[0] ; args_info->version_help = gengetopt_args_info_help[1] ; args_info->algorithm_help = gengetopt_args_info_help[2] ; args_info->capabilities_help = gengetopt_args_info_help[3] ; args_info->delegated_help = gengetopt_args_info_help[4] ; args_info->domains_help = gengetopt_args_info_help[5] ; args_info->id_help = gengetopt_args_info_help[6] ; args_info->in_help = gengetopt_args_info_help[7] ; args_info->out_help = gengetopt_args_info_help[8] ; args_info->label_help = gengetopt_args_info_help[9] ; args_info->wrapkey_help = gengetopt_args_info_help[10] ; } void cmdline_parser_print_version (void) { printf ("%s %s\n", (strlen(CMDLINE_PARSER_PACKAGE_NAME) ? CMDLINE_PARSER_PACKAGE_NAME : CMDLINE_PARSER_PACKAGE), CMDLINE_PARSER_VERSION); if (strlen(gengetopt_args_info_versiontext) > 0) printf("\n%s\n", gengetopt_args_info_versiontext); } static void print_help_common(void) { size_t len_purpose = strlen(gengetopt_args_info_purpose); size_t len_usage = strlen(gengetopt_args_info_usage); if (len_usage > 0) { printf("%s\n", gengetopt_args_info_usage); } if (len_purpose > 0) { printf("%s\n", gengetopt_args_info_purpose); } if (len_usage || len_purpose) { printf("\n"); } if (strlen(gengetopt_args_info_description) > 0) { printf("%s\n\n", gengetopt_args_info_description); } } void cmdline_parser_print_help (void) { int i = 0; print_help_common(); while (gengetopt_args_info_help[i]) printf("%s\n", gengetopt_args_info_help[i++]); } void cmdline_parser_init (struct gengetopt_args_info *args_info) { clear_given (args_info); clear_args (args_info); init_args_info (args_info); } void cmdline_parser_params_init(struct cmdline_parser_params *params) { if (params) { params->override = 0; params->initialize = 1; params->check_required = 1; params->check_ambiguity = 0; params->print_errors = 1; } } struct cmdline_parser_params * cmdline_parser_params_create(void) { struct cmdline_parser_params *params = (struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params)); cmdline_parser_params_init(params); return params; } static void free_string_field (char **s) { if (*s) { free (*s); *s = 0; } } static void cmdline_parser_release (struct gengetopt_args_info *args_info) { free_string_field (&(args_info->algorithm_arg)); free_string_field (&(args_info->algorithm_orig)); free_string_field (&(args_info->capabilities_arg)); free_string_field (&(args_info->capabilities_orig)); free_string_field (&(args_info->delegated_arg)); free_string_field (&(args_info->delegated_orig)); free_string_field (&(args_info->domains_arg)); free_string_field (&(args_info->domains_orig)); free_string_field (&(args_info->id_orig)); free_string_field (&(args_info->in_arg)); free_string_field (&(args_info->in_orig)); free_string_field (&(args_info->out_arg)); free_string_field (&(args_info->out_orig)); free_string_field (&(args_info->label_arg)); free_string_field (&(args_info->label_orig)); free_string_field (&(args_info->wrapkey_arg)); free_string_field (&(args_info->wrapkey_orig)); clear_given (args_info); } static void write_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[]) { FIX_UNUSED (values); if (arg) { fprintf(outfile, "%s=\"%s\"\n", opt, arg); } else { fprintf(outfile, "%s\n", opt); } } int cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info) { int i = 0; if (!outfile) { fprintf (stderr, "%s: cannot dump options to stream\n", CMDLINE_PARSER_PACKAGE); return EXIT_FAILURE; } if (args_info->help_given) write_into_file(outfile, "help", 0, 0 ); if (args_info->version_given) write_into_file(outfile, "version", 0, 0 ); if (args_info->algorithm_given) write_into_file(outfile, "algorithm", args_info->algorithm_orig, 0); if (args_info->capabilities_given) write_into_file(outfile, "capabilities", args_info->capabilities_orig, 0); if (args_info->delegated_given) write_into_file(outfile, "delegated", args_info->delegated_orig, 0); if (args_info->domains_given) write_into_file(outfile, "domains", args_info->domains_orig, 0); if (args_info->id_given) write_into_file(outfile, "id", args_info->id_orig, 0); if (args_info->in_given) write_into_file(outfile, "in", args_info->in_orig, 0); if (args_info->out_given) write_into_file(outfile, "out", args_info->out_orig, 0); if (args_info->label_given) write_into_file(outfile, "label", args_info->label_orig, 0); if (args_info->wrapkey_given) write_into_file(outfile, "wrapkey", args_info->wrapkey_orig, 0); i = EXIT_SUCCESS; return i; } int cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info) { FILE *outfile; int i = 0; outfile = fopen(filename, "w"); if (!outfile) { fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename); return EXIT_FAILURE; } i = cmdline_parser_dump(outfile, args_info); fclose (outfile); return i; } void cmdline_parser_free (struct gengetopt_args_info *args_info) { cmdline_parser_release (args_info); } /** @brief replacement of strdup, which is not standard */ char * gengetopt_strdup (const char *s) { char *result = 0; if (!s) return result; result = (char*)malloc(strlen(s) + 1); if (result == (char*)0) return (char*)0; strcpy(result, s); return result; } int cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info) { return cmdline_parser2 (argc, argv, args_info, 0, 1, 1); } int cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params) { int result; result = cmdline_parser_internal (argc, argv, args_info, params, 0); if (result == EXIT_FAILURE) { cmdline_parser_free (args_info); exit (EXIT_FAILURE); } return result; } int cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required) { int result; struct cmdline_parser_params params; params.override = override; params.initialize = initialize; params.check_required = check_required; params.check_ambiguity = 0; params.print_errors = 1; result = cmdline_parser_internal (argc, argv, args_info, ¶ms, 0); if (result == EXIT_FAILURE) { cmdline_parser_free (args_info); exit (EXIT_FAILURE); } return result; } int cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name) { int result = EXIT_SUCCESS; if (cmdline_parser_required2(args_info, prog_name, 0) > 0) result = EXIT_FAILURE; if (result == EXIT_FAILURE) { cmdline_parser_free (args_info); exit (EXIT_FAILURE); } return result; } int cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error) { int error_occurred = 0; FIX_UNUSED (additional_error); /* checks for required options */ if (! args_info->algorithm_given) { fprintf (stderr, "%s: '--algorithm' ('-a') option required%s\n", prog_name, (additional_error ? additional_error : "")); error_occurred = 1; } if (! args_info->capabilities_given) { fprintf (stderr, "%s: '--capabilities' ('-c') option required%s\n", prog_name, (additional_error ? additional_error : "")); error_occurred = 1; } if (! args_info->domains_given) { fprintf (stderr, "%s: '--domains' ('-d') option required%s\n", prog_name, (additional_error ? additional_error : "")); error_occurred = 1; } if (! args_info->in_given) { fprintf (stderr, "%s: '--in' option required%s\n", prog_name, (additional_error ? additional_error : "")); error_occurred = 1; } if (! args_info->out_given) { fprintf (stderr, "%s: '--out' option required%s\n", prog_name, (additional_error ? additional_error : "")); error_occurred = 1; } if (! args_info->label_given) { fprintf (stderr, "%s: '--label' ('-l') option required%s\n", prog_name, (additional_error ? additional_error : "")); error_occurred = 1; } if (! args_info->wrapkey_given) { fprintf (stderr, "%s: '--wrapkey' ('-k') option required%s\n", prog_name, (additional_error ? additional_error : "")); error_occurred = 1; } /* checks for dependences among options */ return error_occurred; } static char *package_name = 0; /** * @brief updates an option * @param field the generic pointer to the field to update * @param orig_field the pointer to the orig field * @param field_given the pointer to the number of occurrence of this option * @param prev_given the pointer to the number of occurrence already seen * @param value the argument for this option (if null no arg was specified) * @param possible_values the possible values for this option (if specified) * @param default_value the default value (in case the option only accepts fixed values) * @param arg_type the type of this option * @param check_ambiguity @see cmdline_parser_params.check_ambiguity * @param override @see cmdline_parser_params.override * @param no_free whether to free a possible previous value * @param multiple_option whether this is a multiple option * @param long_opt the corresponding long option * @param short_opt the corresponding short option (or '-' if none) * @param additional_error possible further error specification */ static int update_arg(void *field, char **orig_field, unsigned int *field_given, unsigned int *prev_given, char *value, const char *possible_values[], const char *default_value, cmdline_parser_arg_type arg_type, int check_ambiguity, int override, int no_free, int multiple_option, const char *long_opt, char short_opt, const char *additional_error) { char *stop_char = 0; const char *val = value; int found; char **string_field; FIX_UNUSED (field); stop_char = 0; found = 0; if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given))) { if (short_opt != '-') fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n", package_name, long_opt, short_opt, (additional_error ? additional_error : "")); else fprintf (stderr, "%s: `--%s' option given more than once%s\n", package_name, long_opt, (additional_error ? additional_error : "")); return 1; /* failure */ } FIX_UNUSED (default_value); if (field_given && *field_given && ! override) return 0; if (prev_given) (*prev_given)++; if (field_given) (*field_given)++; if (possible_values) val = possible_values[found]; switch(arg_type) { case ARG_SHORT: if (val) *((short *)field) = (short)strtol (val, &stop_char, 0); break; case ARG_STRING: if (val) { string_field = (char **)field; if (!no_free && *string_field) free (*string_field); /* free previous string */ *string_field = gengetopt_strdup (val); } break; default: break; }; /* check numeric conversion */ switch(arg_type) { case ARG_SHORT: if (val && !(stop_char && *stop_char == '\0')) { fprintf(stderr, "%s: invalid numeric value: %s\n", package_name, val); return 1; /* failure */ } break; default: ; }; /* store the original value */ switch(arg_type) { case ARG_NO: break; default: if (value && orig_field) { if (no_free) { *orig_field = value; } else { if (*orig_field) free (*orig_field); /* free previous string */ *orig_field = gengetopt_strdup (value); } } }; return 0; /* OK */ } int cmdline_parser_internal ( int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params, const char *additional_error) { int c; /* Character of the parsed option. */ int error_occurred = 0; struct gengetopt_args_info local_args_info; int override; int initialize; int check_required; int check_ambiguity; package_name = argv[0]; /* TODO: Why is this here? It is not used anywhere. */ override = params->override; FIX_UNUSED(override); initialize = params->initialize; check_required = params->check_required; /* TODO: Why is this here? It is not used anywhere. */ check_ambiguity = params->check_ambiguity; FIX_UNUSED(check_ambiguity); if (initialize) cmdline_parser_init (args_info); cmdline_parser_init (&local_args_info); optarg = 0; optind = 0; opterr = params->print_errors; optopt = '?'; while (1) { int option_index = 0; static struct option long_options[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'V' }, { "algorithm", 1, NULL, 'a' }, { "capabilities", 1, NULL, 'c' }, { "delegated", 1, NULL, 'e' }, { "domains", 1, NULL, 'd' }, { "id", 1, NULL, 'i' }, { "in", 1, NULL, 0 }, { "out", 1, NULL, 0 }, { "label", 1, NULL, 'l' }, { "wrapkey", 1, NULL, 'k' }, { 0, 0, 0, 0 } }; c = getopt_long (argc, argv, "hVa:c:e:d:i:l:k:", long_options, &option_index); if (c == -1) break; /* Exit from `while (1)' loop. */ switch (c) { case 'h': /* Print help and exit. */ cmdline_parser_print_help (); cmdline_parser_free (&local_args_info); exit (EXIT_SUCCESS); case 'V': /* Print version and exit. */ cmdline_parser_print_version (); cmdline_parser_free (&local_args_info); exit (EXIT_SUCCESS); case 'a': /* Object algorithm. */ if (update_arg( (void *)&(args_info->algorithm_arg), &(args_info->algorithm_orig), &(args_info->algorithm_given), &(local_args_info.algorithm_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "algorithm", 'a', additional_error)) goto failure; break; case 'c': /* Object capabilities. */ if (update_arg( (void *)&(args_info->capabilities_arg), &(args_info->capabilities_orig), &(args_info->capabilities_given), &(local_args_info.capabilities_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "capabilities", 'c', additional_error)) goto failure; break; case 'e': /* Object delegates capabilities. */ if (update_arg( (void *)&(args_info->delegated_arg), &(args_info->delegated_orig), &(args_info->delegated_given), &(local_args_info.delegated_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "delegated", 'e', additional_error)) goto failure; break; case 'd': /* Object domains. */ if (update_arg( (void *)&(args_info->domains_arg), &(args_info->domains_orig), &(args_info->domains_given), &(local_args_info.domains_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "domains", 'd', additional_error)) goto failure; break; case 'i': /* Object ID. */ if (update_arg( (void *)&(args_info->id_arg), &(args_info->id_orig), &(args_info->id_given), &(local_args_info.id_given), optarg, 0, "0", ARG_SHORT, check_ambiguity, override, 0, 0, "id", 'i', additional_error)) goto failure; break; case 'l': /* Object label. */ if (update_arg( (void *)&(args_info->label_arg), &(args_info->label_orig), &(args_info->label_given), &(local_args_info.label_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "label", 'l', additional_error)) goto failure; break; case 'k': /* Key to wrap data with (filename). */ if (update_arg( (void *)&(args_info->wrapkey_arg), &(args_info->wrapkey_orig), &(args_info->wrapkey_given), &(local_args_info.wrapkey_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "wrapkey", 'k', additional_error)) goto failure; break; case 0: /* Long option with no short option */ /* Input data (filename). */ if (strcmp (long_options[option_index].name, "in") == 0) { if (update_arg( (void *)&(args_info->in_arg), &(args_info->in_orig), &(args_info->in_given), &(local_args_info.in_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "in", '-', additional_error)) goto failure; } /* Output data (filename). */ else if (strcmp (long_options[option_index].name, "out") == 0) { if (update_arg( (void *)&(args_info->out_arg), &(args_info->out_orig), &(args_info->out_given), &(local_args_info.out_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "out", '-', additional_error)) goto failure; } break; case '?': /* Invalid option. */ /* `getopt_long' already printed an error message. */ goto failure; default: /* bug: option not considered. */ fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : "")); abort (); } /* switch */ } /* while */ if (check_required) { error_occurred += cmdline_parser_required2 (args_info, argv[0], additional_error); } cmdline_parser_release (&local_args_info); if ( error_occurred ) return (EXIT_FAILURE); return 0; failure: cmdline_parser_release (&local_args_info); return (EXIT_FAILURE); } /* vim: set ft=c noet ts=8 sts=8 sw=8 tw=80 nojs spell : */ yubihsm-shell-2.7.1/CHANGELOG0000644000175100017510000003062015133003406015122 0ustar runnerrunner=== Version 2.7.1 shell: Add support for decrypt-oaep command in non-interactive mode test: Improve testing processes === Version 2.7.0 lib: shell: pkcs11: Add support for compressing X509Certificate before import shell: Add subcommand to generate certificate signing request (CSR) test: Increase test coverage === Version 2.6.0 lib: shell: pkcs11: Add support for asymmetric wrap pkcs11: Add support for PKCS11 3.0 shell: Fix opening a session using credentials stored on a YubiKey build: Always compile with YubiHSM Auth enabled === Version 2.5.0 pkcs11: Add support for applying KDF after ECDH derivation pkcs11: Shell: Fix minor bugs test: Increase test coverage === Version 2.4.2 pkcs11: Add Symmetric key capabilities to searchable criteria pkcs11: Add support for CKA_KEY_TYPE when searching for objects pkcs11: Add support for CKA_MODIFIABLE and CKA_COPYABLE attributes for AES and Wrap keys test: Increase test coverage === Version 2.4.1 pkcs11: Security update for https://www.yubico.com/support/security-advisories/ysa-2023-01/[YSA-2023-01] pkcs11: Allow only a user with access to all the object's domains to edit its attributes pkcs11: Allow for the creation of an asymmetric key even if CKA_ID or CKA_LABEL attribute values for the private and public key are different. pkcs11: Improve backup capabilities of objects whose attributes have been changed pkcs11: Add support for CKA_ALLOWED_MECHANISMS pkcs11: Fix CKA_SENSITIVE and CKA_PRIVATE return value for opaque objects pkcs11: Add support for CKA_EXTRACTABLE for imported certificates pkcs11: Fix regression that only allowed encryption with private keys lib: pkcs11: Delay client side MAC check to avoid leaving unauthenticated sessions open shell: Fix handling of ED25519 keys build: Update release script for Centos7 build: Fix paths in pkg-config template build: Set linker flags by platform test: Improve test coverage === Version 2.4.0 lib: shell: pkcs11: Add support for symmetric encryption, AES-ECB and AES-CBC (Requires firmware version 2.3 and later) shell: Enable asymmetric authentication by default (Requires firmware version 2.3 and later) shell: Allow hex format when creating symmetric authentication key shell: Improve usage of the list command shell: Allow yubihsm-auth reader to be specified shell: Enable backend TLS support in the command line pkcs11: Add support for modifying CKA_ID and CKA_LABEL attribute values pkcs11: Improve handling of attributes pkcs11: Improve debug output pkcs11: Improve error handling pkcs11: Change in firmware/harware version representation. The version as reported by C_GetSlotInfo and C_GetTokenInfo will now show minor*10+patch, instead of minor*100+patch build: Dependecy updates === Version 2.3.2 shell: Remove limit on input file size shell: pkcs11: build: Minor improvements === Version 2.3.1 lib: Fix handling errors received from the YubiHSM shell: Enforce valid DER certificate when importing a certificate shell: Support PEM in-format when importing a certificate shell: pkcs11: Fix minor memory leaks pkcs11: Better handling of invalid input build: Better build experience on MacOS build: Better usage of security flags build: Improve scripts to build debian packages test: Improve testing === Version 2.3.0a build: Enable additional hardening flags when building with CMake < 3.14 === Version 2.3.0 lib: Security update for https://www.yubico.com/support/security-advisories/ysa-2021-04/[YSA-2021-04] lib: Improve backend loading on Windows lib: Add support for ecdh primitives using bcrypt on Windows lib: cli: Improve error handling lib: pkcs11: Add more connection option lib: pkcs11: cli: Fix minor bugs cli: Rename set-option to put-option and add support for get-option pkcs11: Add support for RSA encryption yubihsm-auth: No PSCS reader name filtering by default build: Add version details to yubihsm_pkcs11 module and libykhsmauth library files on Windows build: Make minimum CMake version required 3.5 test: Improved testing === Version 2.2.0 shell: Enable ykhsmauth to be used from commandline ykhsmauth: lib: Add support for YubiCrypt authentication yubihsm-auth: Add CLI for YubiCrypt authentication === Version 2.1.0 lib: Security update for https://www.yubico.com/support/security-advisories/ysa-2021-01/[YSA-2021-01] lib: Add FIPS-mode option lib: Add support for rsa-pkcs1-decrypt algorithm lib: shell: Add support for OTP AEAD rewrap shell: Add support writing attestation certificate to a file pkcs11: Add support for CKA_TRUSTED attribute all: Fix potential memory leaks all: Improve error handling doc: Clarify the minimum length of the password used with PKCS11 === Version 2.0.3 all: Move away from archaic offensive terms all: Update build scripts to account for changes in newer MACOS all: Build on Windows with Visual Studio 2019 pkcs11: Enable .Net to load yubihsm-pkcs11.dylib lib: Fix memory leaks lib: Security fixes lib: Add a session identifier for the backend lib: Make the backend more thread-safe on Windows shell: Honor the base64 format when returning a public key shell: Honor the PEM format when returning a certificate shell: Improve parsing of command line arguments when using OAEP decryption shell: Add support for special (national) characters test: Improve testing === Version 2.0.2 yhauth: Report touch policy as part of the "list" command ykyh: Allow reading the password from stdin yhwrap: Fix wrapping of ED25519 keys shell: Fix ED25519 public key PEM formatting shell: Replace unprintable characters in the object label with '.' ci: Fail early if DEFAULT_CONNECTOR_URL is not set ci: Update homebrew dependencies build: Add two bionic-based builds build: Fix 32-bit Windows builds with mingw32/gcc7 build: Ensure that PCSC is not automatically used on Windows tool: Stop the timer for keepalive functionality while reading the password string misc: Allow disabling link time optimization. misc: Fixes and improvements to build, work and test on FreeBSD. === Version 2.0.1 shell: Add "blink-device" command in CLI mode shell: Add "set-log-index" command to CLI mode shell: Add "exit" as an alias to the "quit" command. shell: Add an optional output file to "audit get" command shell: No openning a session for commands that do not need one shell/yhwrap/pkcs11: open all files in binary mode to keep Windows from changing line ends shell: Install the sigalarm handler in CLI mode build: Add support for installing to lib64 on Fedora build: Only use LTO on clang > 7 build: Add a library only build option examples: Improve code examples test: Tests are improved and are better adapted for MacOS pkcs11/tests: Only run ecdh engine tests on openssl 1.1+ lib: Improve handling of device memory lib: Allow both USB and HTTP support to be compiled in static library lib: Implement signing using sign-eddsa lib: Add the possibility to generate authkey specifying all the capabilities in their string form lib/curl: Include the curl strerror in debug when a connection fails doc: Improvement in documentation, README files and command help === Version 2.0.0 lib: Fix issue with session creation if the authentication key ID is too high lib: Fix a potential issue with memory operations lib: Fix a potential issue with data left after previous transactions or connections lib: Better documentation of arguments lib: Better handling of errors lib: Rename object types, algorithms, capabilities, commands, command options and errors lib: API improvements lib: Add a feature to derive an authentication key from a password lib: Add a feature to change an authentication key pkcs11: Added support for C_DeriveKey() shell: More efficient use of the keepalive function shell: More efficient handling of sessions when a connection is terminated shell: Change keepalive command to a toggle (on/off) tests: Make code examples compile tests: Add support for running tests using direct USB connection all: Drop unused files all: Re-organization of file structure doc: Drop documentation from the code base and moved the content to Yubico's developers website (https://developers.yubico.com/YubiHSM2/) === Version 1.0.4 pkcs11: Fix a potential issue with RSA bit calculation in C_GetMechanismInfo() pkcs11: Fix a case where we return the wrong error from C_GetMechanismList() pkcs11: Add a way for users to pass in options over the API to C_Initialize() connector: Fix a race condition when the usb state was re-created. connector: Better error reporting in some failure cases. connector: Fix issues where the connector could hang on Windows. connector: Fix an issue where the connector would not reconnect on Windows. shell: Fix an issue with importing HMAC keys. === Version 1.0.3 shell: Handle return values from reset correctly on windows. connector: Return HTTP errors when operations fail. lib: Handle HTTP errors correctly on windows. lib: Fix printing of time in debug on windows. pkcs11: Fix a problem in C_FindObjects() where not all items would be returned === Version 1.0.2 lib: Fix connect timeout on windows lib: Fix debugging to file lib/pkcs11/shell: Openssl 1.1 compatibility lib: Mark internal symbols as hidden correctly pkcs11: Fix an error case leaving the session in a broken state pkcs11: Start session IDs from 1, not 0 pkcs11: Add option to set connect timeout pkcs11: Accept C_SetAttributeValue() for CKA_ID and CKA_LABEL if unchanged setup: Fix broken debian package shell: Implement decrypt-ecdh in non-interactive mode connector: On Windows use internal USB libraries instead of libusb connector: Implement Host header allow listing (Use to prevent DNS rebinding attacks in applicable environments, e.g., if there is an absolute need to use a web browser on the host where the Yubihsm2 is installed to connect to untrusted web sites on the Internet. This is not a recommended practice.) === Version 1.0.1 shell: Fix hashing so signing from windows shell works shell: Sorted output pkcs11: Handle ecdsa with longer hash than key pkcs11: Correct error for trying to extract EC key pkcs11: Fix native locking on windows pkcs11: Correct linking on macos lib: Fix logic in session re-use lib: Mark all internal symbols as hidden ksp: Handle passwords longer than 8 characters all: Provide deb packages on debian/ubuntu === Version 0.2.1 doc: add Compatibility.adoc doc: fixup GET LOGS text doc: fixup GET LOGS stanza doc: fixup GET OBJECT INFO text doc: add text about pkcs11 configuration examples/attest: add reading out of cert after loading it examples/import_rsa: change import_rsa example to use pss signing examples: add wrap_data example examples: change all examples to use yh_parse_domains lib/tool/doc: add blink command log: add yh_set_connector_option for transport options lib: give create_session functions a reopen option lib: add OBJECT_EXISTS error lib: allow yh_util_get_object_info to not fill in an object lib: implement yh_util_reset lib: new function for setting debug output: yh_set_debug_output pkcs11: add CKA_ENCRYPT and CKA_VERIFY to public keys pkcs11: add an offset to the vendor defined values pkcs11: add checks for boolean attributes we just accept pkcs11: add configfile options for setting verbosity pkcs11: add debug output file to pkcs11 config pkcs11: don't set CKF_DECRYPT for pkcs+hash mechanisms pkcs11: fix verify for CKM_RSA_PKCS_PSS pkcs11: fixup for C_FindObjectsInit being called without logging in pkcs11: fixup session release in C_CloseSession pkcs11: ignore CKA_APPLICATION in object filtering pkcs11: ignore CKA_KEY_TYPE in C_FindObjectsInit pkcs11: in C_FindObjectsInit make more initial state earlier pkcs11: in C_FindObjectsInit set operation type as late as possible pkcs11: in C_GetSlotList detect overflow more reliably pkcs11: move CKA_ENCRYPT and CKA_VERIFY from hard true on pubkey pkcs11: move CKA_VERIFY and CKA_ENCRYPT from hard true for ec pubkey pkcs11: move wrap/unwrap on rsa generate to unchecked pkcs11: never try to delete a public key, lie and say it's fine instead pkcs11: print more debug info on OAEP mechanism error pkcs11: remove some skipped pkcs11test tests, we fail them correctly pkcs11: return CKR_ATTRIBUTE_SENSITIVE on CKA_PRIVATE_EXPONENT pkcs11: truncate CKA_ID to two bytes if it's longer pkcs11: when closing the debug output file, reset it to stderr tool: drop local connector spawn code tool: add decrypt ecdh command tool: add decrypt oaep command tool: add output for decrypt pkcs1v15 tool: cleanup created objects after benchmark tool: fixup otp decrypt that has to hex decode the otp tool: for ecdh benchmarks delete the temporary key tool: print a message when doing benchmark setup tool: make the reset command print nicer messages yhwrap: add hmac key pre-split yubihsm-shell-2.7.1/resources/0000755000175100017510000000000015133003406015721 5ustar runnerrunneryubihsm-shell-2.7.1/resources/tests/0000755000175100017510000000000015133003406017063 5ustar runnerrunneryubihsm-shell-2.7.1/resources/tests/ps1/0000755000175100017510000000000015133003406017566 5ustar runnerrunneryubihsm-shell-2.7.1/resources/tests/ps1/test_otpaeadkey.ps10000644000175100017510000001242415133003406023403 0ustar runnerrunner$ARCH=$args[0] if($ARCH -eq "x86") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files (x86)/Yubico/YubiHSM Shell/bin" } } elseif ($ARCH -eq "x64") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files/Yubico/YubiHSM Shell/bin" } } else { echo "Usage: ./cmdline_test.ps1 " echo "" echo "This is a test script that uses the yubihsm-shell command line tool to reset the conncted YubiHSM and then different commands." echo "" echo " x86 expects that yubihsm-shell.exe is installed in 'C:/Program Files (x86)/Yubico/Yubico PIV Tool/bin'" echo " x64 expects that yubhsm-shell.exe is installed in 'C:/Program Files/Yubico/Yubico PIV Tool/bin'" exit } echo "Running commands on $ARCH architecture" $TEST_DIR = "yubihsm-shell_test_dir" Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue New-Item $TEST_DIR -type Directory -Force cd $TEST_DIR echo "test signing data" > data.txt Set-PSDebug -Trace 1 $ErrorActionPreference = "Stop" function CheckExitStatus { param ( $ECode ) if(!$ECode) { echo "Fail!" exit } } $keyid=100 echo "---------------------- HAMC keys --------------------- " echo "**********************************" echo " AEAD Key 128" echo "**********************************" echo "=== Generate on YubiHSM" yubihsm-shell.exe -p password -a generate-otp-aead-key -i $keyid -l "aeadkey" -d "1,2,3" -c "randomize-otp-aead" -A "aes128-yubico-otp" --nonce 0x01020304; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t otp-aead-key > info.txt; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "id: 0x0064"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "type: otp-aead-key"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "algorithm: aes128-yubico-otp"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern 'label: "aeadkey"'; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "domains: 1:2:3"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "origin: generated"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "capabilities: randomize-otp-aead"; CheckExitStatus -ECode $? echo "=== Randomize OTP AEAD" yubihsm-shell.exe -p password -a randomize-otp-aead -i $keyid; CheckExitStatus -ECode $? echo "=== Delete keys" yubihsm-shell.exe -p password -a delete-object -i $keyid -t otp-aead-key; CheckExitStatus -ECode $? echo "**********************************" echo " AEAD Key 192" echo "**********************************" echo "=== Generate on YubiHSM" yubihsm-shell.exe -p password -a generate-otp-aead-key -i $keyid -l "aeadkey" -d "1,2,3" -c "randomize-otp-aead" -A "aes192-yubico-otp" --nonce 0x01020304; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t otp-aead-key > info.txt; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "id: 0x0064"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "type: otp-aead-key"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "algorithm: aes192-yubico-otp"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern 'label: "aeadkey"'; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "domains: 1:2:3"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "origin: generated"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "capabilities: randomize-otp-aead"; CheckExitStatus -ECode $? echo "=== Randomize OTP AEAD" yubihsm-shell.exe -p password -a randomize-otp-aead -i $keyid; CheckExitStatus -ECode $? echo "=== Delete keys" yubihsm-shell.exe -p password -a delete-object -i $keyid -t otp-aead-key; CheckExitStatus -ECode $? echo "**********************************" echo " AEAD Key 256" echo "**********************************" echo "=== Generate on YubiHSM" yubihsm-shell.exe -p password -a generate-otp-aead-key -i $keyid -l "aeadkey" -d "1,2,3" -c "randomize-otp-aead" -A "aes256-yubico-otp" --nonce 0x01020304; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t otp-aead-key > info.txt; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "id: 0x0064"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "type: otp-aead-key"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "algorithm: aes256-yubico-otp"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern 'label: "aeadkey"'; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "domains: 1:2:3"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "origin: generated"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "capabilities: randomize-otp-aead"; CheckExitStatus -ECode $? echo "=== Randomize OTP AEAD" yubihsm-shell.exe -p password -a randomize-otp-aead -i $keyid; CheckExitStatus -ECode $? echo "=== Delete keys" yubihsm-shell.exe -p password -a delete-object -i $keyid -t otp-aead-key; CheckExitStatus -ECode $? cd .. Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue Set-PSDebug -Trace 0yubihsm-shell-2.7.1/resources/tests/ps1/cmdline_test.ps10000644000175100017510000001021315133003406022662 0ustar runnerrunner$ARCH=$args[0] if($ARCH -eq "x86") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files (x86)/Yubico/YubiHSM Shell/bin" } } elseif ($ARCH -eq "x64") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files/Yubico/YubiHSM Shell/bin" } } else { echo "Usage: ./cmdline_test.ps1 " echo "" echo "This is a test script that uses the yubihsm-shell command line tool to reset the conncted YubiHSM and then different com mands." echo "" echo " x86 expects that yubihsm-shell.exe is installed in 'C:/Program Files (x86)/Yubico/Yubico PIV Tool/bin'" echo " x64 expects that yubhsm-shell.exe is installed in 'C:/Program Files/Yubico/Yubico PIV Tool/bin'" exit } echo "Running commands on $ARCH architecture" $TEST_DIR = "yubihsm-shell_test_dir" Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue New-Item $TEST_DIR -type Directory -Force Set-PSDebug -Trace 1 $ErrorActionPreference = "Stop" function CheckExitStatus { param ( $ECode ) if(!$ECode) { echo "Fail!" exit } } yubihsm-shell.exe --version; CheckExitStatus -ECode $? yubihsm-shell.exe --help; CheckExitStatus -ECode $? yubihsm-shell.exe -a get-device-info; CheckExitStatus -ECode $? echo "********************** Reset YubiHSM ********************* " yubihsm-shell.exe -p password -a reset; CheckExitStatus -ECode $? Start-Sleep -s 10 echo "********************** Blink ********************* " yubihsm-shell.exe -p password -a blink; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a blink --duration=5; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a blink-device; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a blink-device --duration=5; CheckExitStatus -ECode $? echo "********************** Get Pseudo-random ********************* " yubihsm-shell.exe -p password -a get-pseudo-random; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-pseudo-random --count=10; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-pseudo-random --count=10 --out=random.txt; CheckExitStatus -ECode $? rm random.txt echo "********************** Asym keys ********************* " & "$PSScriptRoot\test_edkey.ps1" "$ARCH" & "$PSScriptRoot\test_eckey.ps1" "$ARCH" & "$PSScriptRoot\test_rsakey.ps1" "$ARCH" echo "********************** HMAC keys ********************* " & "$PSScriptRoot\test_hmackey.ps1" "$ARCH" echo "********************** AEAD keys ********************* " & "$PSScriptRoot\test_otpaeadkey.ps1" "$ARCH" Set-PSDebug -Trace 1 #echo "********************** Template ********************* " #echo "=== Import template" #$id=100 #yubihsm-shell.exe -p password -a get-pseudo-random --count=512 --out=template.txt; CheckExitStatus -ECode $? #yubihsm-shell.exe -p password -a put-template -i $id -l template -d 1 -A template-ssh --in template.txt; CheckExitStatus -ECode $? #yubihsm-shell.exe -p password -a get-object-info -i $id -t template; CheckExitStatus -ECode $? #echo "=== Get template" #yubihsm-shell.exe -p password -a get-template -i $id; CheckExitStatus -ECode $? #echo "=== Delete template" #yubihsm-shell.exe -p password -a delete-object -i $id -t template; CheckExitStatus -ECode $? #rm template.txt #echo "********************** Wrap keys ********************* " echo "********************** Authentication keys ********************* " echo "=== Create new authentication key" $id=200 yubihsm-shell.exe -p password -a put-authentication-key -i $id -l authkey -d 1,2,3 -c all --new-password foo123; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $id -t authentication-key; CheckExitStatus -ECode $? echo "=== Login using new authetication key" yubihsm-shell.exe --authkey $id -p foo123 -a get-object-info -i 1 -t authentication-key; CheckExitStatus -ECode $? echo "=== Delete new authentication key" yubihsm-shell.exe -p password -a delete-object -i $id -t authentication-key; CheckExitStatus -ECode $? Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue Set-PSDebug -Trace 0yubihsm-shell-2.7.1/resources/tests/ps1/test_edkey.ps10000644000175100017510000000435015133003406022355 0ustar runnerrunner$ARCH=$args[0] if($ARCH -eq "x86") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files (x86)/Yubico/YubiHSM Shell/bin" } } elseif ($ARCH -eq "x64") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files/Yubico/YubiHSM Shell/bin" } } else { echo "Usage: ./cmdline_test.ps1 " echo "" echo "This is a test script that uses the yubihsm-shell command line tool to reset the conncted YubiHSM and then different commands." echo "" echo " x86 expects that yubihsm-shell.exe is installed in 'C:/Program Files (x86)/Yubico/Yubico PIV Tool/bin'" echo " x64 expects that yubhsm-shell.exe is installed in 'C:/Program Files/Yubico/Yubico PIV Tool/bin'" exit } echo "Running commands on $ARCH architecture" $TEST_DIR = "yubihsm-shell_test_dir" Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue New-Item $TEST_DIR -type Directory -Force cd $TEST_DIR echo "test signing data" > data.txt Set-PSDebug -Trace 1 $ErrorActionPreference = "Stop" function CheckExitStatus { param ( $ECode ) if(!$ECode) { echo "Fail!" exit } } echo "---------------------- ED keys --------------------- " # Generate yubihsm-shell.exe -p password -a generate-asymmetric-key -i 100 -l "edKey" -d "1,2,3" -c "sign-eddsa" -A "ed25519"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i 100 -t asymmetric-key; CheckExitStatus -ECode $? # Get public key yubihsm-shell.exe -p password -a get-public-key -i 100 > edkey1.pub; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i 100 --out edkey2.pub; CheckExitStatus -ECode $? # Signing yubihsm-shell.exe -p password -a sign-eddsa -i 100 -A ed25519 --in data.txt > data.ed1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-eddsa -i 100 -A ed25519 --in data.txt --out data.ed2.sig; CheckExitStatus -ECode $? # Delete yubihsm-shell.exe -p password -a delete-object -i 100 -t asymmetric-key; CheckExitStatus -ECode $? cd .. Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue Set-PSDebug -Trace 0yubihsm-shell-2.7.1/resources/tests/ps1/test_hmackey.ps10000644000175100017510000001050615133003406022675 0ustar runnerrunner$ARCH=$args[0] if($ARCH -eq "x86") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files (x86)/Yubico/YubiHSM Shell/bin" } } elseif ($ARCH -eq "x64") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files/Yubico/YubiHSM Shell/bin" } } else { echo "Usage: ./cmdline_test.ps1 " echo "" echo "This is a test script that uses the yubihsm-shell command line tool to reset the conncted YubiHSM and then different commands." echo "" echo " x86 expects that yubihsm-shell.exe is installed in 'C:/Program Files (x86)/Yubico/Yubico PIV Tool/bin'" echo " x64 expects that yubhsm-shell.exe is installed in 'C:/Program Files/Yubico/Yubico PIV Tool/bin'" exit } echo "Running commands on $ARCH architecture" $TEST_DIR = "yubihsm-shell_test_dir" Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue New-Item $TEST_DIR -type Directory -Force cd $TEST_DIR echo "test signing data" > data.txt Set-PSDebug -Trace 1 $ErrorActionPreference = "Stop" function CheckExitStatus { param ( $ECode ) if(!$ECode) { echo "Fail!" exit } } $keyid=100 echo "---------------------- HAMC keys --------------------- " echo "**********************************" echo " hmac-sha1" echo "**********************************" echo "=== Generate on YubiHSM" yubihsm-shell.exe -p password -a generate-hmac-key -i $keyid -l "hmackey" -d "1,2,3" -c "sign-hmac" -A "hmac-sha1"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t hmac-key > info.txt; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "id: 0x0064"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "type: hmac-key"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "algorithm: hmac-sha1"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern 'label: "hmackey"'; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "domains: 1:2:3"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "origin: generated"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "capabilities: sign-hmac"; CheckExitStatus -ECode $? echo "=== Delete keys" yubihsm-shell.exe -p password -a delete-object -i $keyid -t hmac-key; CheckExitStatus -ECode $? echo "**********************************" echo " hmac-sha256" echo "**********************************" echo "=== Generate on YubiHSM" yubihsm-shell.exe -p password -a generate-hmac-key -i $keyid -l "hmackey" -d "1,2,3" -c "sign-hmac" -A "hmac-sha256"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t hmac-key > info.txt; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "algorithm: hmac-sha256"; CheckExitStatus -ECode $? echo "=== Delete keys" yubihsm-shell.exe -p password -a delete-object -i $keyid -t hmac-key; CheckExitStatus -ECode $? echo "**********************************" echo " hmac-sha384" echo "**********************************" echo "=== Generate on YubiHSM" yubihsm-shell.exe -p password -a generate-hmac-key -i $keyid -l "hmackey" -d "1,2,3" -c "sign-hmac" -A "hmac-sha384"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t hmac-key > info.txt; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "algorithm: hmac-sha384"; CheckExitStatus -ECode $? echo "=== Delete keys" yubihsm-shell.exe -p password -a delete-object -i $keyid -t hmac-key; CheckExitStatus -ECode $? echo "**********************************" echo " hmac-sha512" echo "**********************************" echo "=== Generate on YubiHSM" yubihsm-shell.exe -p password -a generate-hmac-key -i $keyid -l "hmackey" -d "1,2,3" -c "sign-hmac" -A "hmac-sha512"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t hmac-key > info.txt; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "algorithm: hmac-sha512"; CheckExitStatus -ECode $? echo "=== Delete keys" yubihsm-shell.exe -p password -a delete-object -i $keyid -t hmac-key; CheckExitStatus -ECode $? cd .. Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue Set-PSDebug -Trace 0yubihsm-shell-2.7.1/resources/tests/ps1/opensc_test.ps10000644000175100017510000000427715133003406022553 0ustar runnerrunner# This script runs on Powershell. If running tests on the current Powershell terminal is not permitted, run the # following command to allow it only on the current terminal: # >> Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process if($args.length -eq 0) { echo "Usage: ./opensc_tests.ps1 " echo "" echo "This script expects that libyubihsm.dll and the libcrypto.dll are on PATH and YUBIHSM_PKCS11_CONF environment variable is defined" exit } if ((Get-Command "pkcs11-tool.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path +=";C:\Program Files\OpenSC Project\OpenSC\tools" } $MODULE=$args[0] #$YHPKCS11CFG=$args[2] #$env:YUBIHSM_PKCS11_CONF=$YHPKCS11CFG Set-PSDebug -Trace 1 echo "******************* Generation Tests ********************* " pkcs11-tool.exe --module $MODULE --login --pin 0001password --keypairgen --id 100 --key-type EC:secp384r1 pkcs11-tool.exe --module $MODULE --login --pin 0001password --keypairgen --id 2 --key-type EC:prime256v1 pkcs11-tool.exe --module $MODULE --login --pin 0001password --keypairgen --id 4 --key-type rsa:2048 pkcs11-tool.exe --module $MODULE --login --pin 0001password --keypairgen --id 5 --key-type rsa:3072 #Set-PSDebug -Trace 0 #exit echo "******************* Signing Tests ********************* " echo "this is test data" > Z:/data.txt pkcs11-tool.exe --module $MODULE --sign --pin 0001password --id 100 -m ECDSA-SHA1 --signature-format openssl -i Z:/data.txt -o Z:/data.sig pkcs11-tool.exe --module $MODULE --sign --pin 0001password --id 2 -m ECDSA-SHA1 --signature-format openssl -i Z:/data.txt -o Z:/data.sig pkcs11-tool.exe --module $MODULE --sign --pin 0001password --id 4 -m SHA512-RSA-PKCS -i Z:/data.txt -o Z:/data.sig pkcs11-tool.exe --module $MODULE --sign --pin 0001password --id 5 -m SHA512-RSA-PKCS -i Z:/data.txt -o Z:/data.sig rm Z:/data.txt rm Z:/data.sig echo "******************* Testing RSA Tests ********************* " pkcs11-tool.exe --module $MODULE --login --pin 0001password --test #echo "******************* Testing EC Tests ********************* " #pkcs11-tool.exe --module $MODULE --login --login-type so --so-pin 0001password --test-ec --id 200 --key-type EC:secp256r1 Set-PSDebug -Trace 0yubihsm-shell-2.7.1/resources/tests/ps1/test_rsakey.ps10000644000175100017510000005311415133003406022554 0ustar runnerrunner$ARCH=$args[0] if($ARCH -eq "x86") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files (x86)/Yubico/YubiHSM Shell/bin" } } elseif ($ARCH -eq "x64") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files/Yubico/YubiHSM Shell/bin" } } else { echo "Usage: ./cmdline_test.ps1 " echo "" echo "This is a test script that uses the yubihsm-shell command line tool to reset the conncted YubiHSM and then different commands." echo "" echo " x86 expects that yubihsm-shell.exe is installed in 'C:/Program Files (x86)/Yubico/Yubico PIV Tool/bin'" echo " x64 expects that yubhsm-shell.exe is installed in 'C:/Program Files/Yubico/Yubico PIV Tool/bin'" exit } echo "Running commands on $ARCH architecture" $TEST_DIR = "yubihsm-shell_test_dir" Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue New-Item $TEST_DIR -type Directory -Force cd $TEST_DIR echo "test signing data" > data.txt Set-PSDebug -Trace 1 $ErrorActionPreference = "Stop" function CheckExitStatus { param ( $ECode ) if(!$ECode) { echo "Fail!" exit } } $keyid=100 $import_keyid=200 echo "---------------------- RSA keys --------------------- " echo "**********************************" echo " RSA2048" echo "**********************************" echo "=== Generate on YubiHSM" yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "rsaKey" -d "1" -c "sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate" -A "rsa2048"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t asymmetric-key > info.txt; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "id: 0x0064"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "type: asymmetric-key"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "algorithm: rsa2048"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern 'label: "rsaKey"'; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "domains: 1"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "origin: generated"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "capabilities: decrypt-oaep:decrypt-pkcs:sign-attestation-certificate:sign-pkcs:sign-pss"; CheckExitStatus -ECode $? rm info.txt echo "=== Get public key of generated key" yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM --out pubkey.pem; CheckExitStatus -ECode $? echo "=== Import into YubiHSM" openssl.exe genrsa -out rsa2048-keypair.pem 2048; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "rsaKeyImport" -d "2" -c "sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate" --in=rsa2048-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $import_keyid -t asymmetric-key > info.txt; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "id: 0x00c8"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "type: asymmetric-key"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "algorithm: rsa2048"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern 'label: "rsaKeyImport"'; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "domains: 2"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "origin: imported"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "capabilities: decrypt-oaep:decrypt-pkcs:sign-attestation-certificate:sign-pkcs:sign-pss"; CheckExitStatus -ECode $? echo "=== Get public key of imported key" yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM --out pubkey_imported.pem; CheckExitStatus -ECode $? echo "=== Signing with generated key and" echo "===== rsa-pkcs1-sha1" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha1 --in data.txt --out data.2048pkcs1sha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha256" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha256 --in data.txt --out data.2048pkcs1sha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha384" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha384 --in data.txt --out data.2048pkcs1sha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha512" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha512 --in data.txt --out data.2048pkcs1sha512.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha1" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha1 --in data.txt --out data.2048psssha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha256" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha256 --in data.txt --out data.2048psssha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha384" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha384 --in data.txt --out data.2048psssha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha512" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha512 --in data.txt --out data.2048psssha512.sig; CheckExitStatus -ECode $? echo "=== Signing with imported key and" echo "===== rsa-pkcs1-sha1" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha1 --in data.txt --out data.2048pkcs1sha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha256" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha256 --in data.txt --out data.2048pkcs1sha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha384" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha384 --in data.txt --out data.2048pkcs1sha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha512" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha512 --in data.txt --out data.2048pkcs1sha512.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha1" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha1 --in data.txt --out data.2048psssha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha256" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha256 --in data.txt --out data.2048psssha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha384" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha384 --in data.txt --out data.2048psssha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha512" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha512 --in data.txt --out data.2048psssha512.sig; CheckExitStatus -ECode $? echo "=== Make self signed certificate" yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? echo "=== Sign attestation certificate" yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? echo "=== Decrypt with generated key and PKCS1v15" openssl.exe rsautl -encrypt -inkey pubkey.pem -pubin -in data.txt -out data.enc; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a decrypt-pkcs1v15 -i $keyid --in data.enc --out data.dec; CheckExitStatus -ECode $? if (@(Compare-Object $(Get-Content "data.txt") $(Get-Content "data.dec") -sync 0).length -ne 0) { echo "Decrypt failed" exit 2 } rm data.dec echo "=== Decrypt with imported key and PKCS1v15" openssl.exe rsautl -encrypt -inkey pubkey_imported.pem -pubin -in data.txt -out data.enc; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a decrypt-pkcs1v15 -i $import_keyid --in data.enc --out data.dec; CheckExitStatus -ECode $? if (@(Compare-Object $(Get-Content "data.txt") $(Get-Content "data.dec") -sync 0).length -ne 0) { echo "Decrypt failed" exit 2 } rm data.dec echo "=== Delete keys" yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? echo "**********************************" echo " RSA3072" echo "**********************************" echo "=== Generate on YubiHSM" yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "rsaKey" -d "1" -c "sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate" -A "rsa3072"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? echo "=== Get public key of generated key" yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM --out pubkey.pem; CheckExitStatus -ECode $? echo "=== Import into YubiHSM" openssl.exe genrsa -out rsa3072-keypair.pem 3072; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "rsaKeyImport" -d "2" -c "sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate" --in=rsa3072-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? echo "=== Get public key of imported key" yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM --out pubkey_imported.pem; CheckExitStatus -ECode $? echo "=== Signing with generated key and" echo "===== rsa-pkcs1-sha1" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha1 --in data.txt --out data.3072pkcs1sha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha256" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha256 --in data.txt --out data.3072pkcs1sha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha384" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha384 --in data.txt --out data.3072pkcs1sha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha512" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha512 --in data.txt --out data.3072pkcs1sha512.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha1" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha1 --in data.txt --out data.3072psssha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha256" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha256 --in data.txt --out data.3072psssha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha384" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha384 --in data.txt --out data.3072psssha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha512" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha512 --in data.txt --out data.3072psssha512.sig; CheckExitStatus -ECode $? echo "=== Signing with imported key and" echo "===== rsa-pkcs1-sha1" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha1 --in data.txt --out data.3072pkcs1sha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha256" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha256 --in data.txt --out data.3072pkcs1sha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha384" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha384 --in data.txt --out data.3072pkcs1sha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha512" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha512 --in data.txt --out data.3072pkcs1sha512.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha1" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha1 --in data.txt --out data.3072psssha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha256" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha256 --in data.txt --out data.3072psssha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha384" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha384 --in data.txt --out data.3072psssha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha512" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha512 --in data.txt --out data.3072psssha512.sig; CheckExitStatus -ECode $? echo "=== Make self signed certificate" yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? #yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? echo "=== Sign attestation certificate" yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? <# echo "=== Decrypt with generated key and PKCS1v15" openssl rsautl -encrypt -inkey pubkey.pem -pubin -in data.txt -out data.enc yubihsm-shell.exe -p password -a decrypt-pkcs1v15 -i $keyid --in data.enc --out data.dec if (@(Compare-Object $(Get-Content "data.txt") $(Get-Content "data.dec") -sync 0).length -ne 0) { echo "Decrypt failed" exit 2 } rm data.dec echo "=== Decrypt with imported key and PKCS1v15" openssl.exe rsautl -encrypt -inkey pubkey_imported.pem -pubin -in data.txt -out data.enc yubihsm-shell.exe -p password -a decrypt-pkcs1v15 -i $import_keyid --in data.enc --out data.dec <# if (@(Compare-Object $(Get-Content "data.txt") $(Get-Content "data.dec") -sync 0).length -ne 0) { echo "Decrypt failed" exit 2 } rm data.dec #> echo "=== Delete keys" yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? # RSA 4096 echo "**********************************" echo " RSA4096" echo "**********************************" echo "=== Generate on YubiHSM" yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "rsaKey" -d "1" -c "sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate" -A "rsa4096"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? echo "=== Get public key of generated key" yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM --out pubkey.pem; CheckExitStatus -ECode $? echo "=== Import into YubiHSM" openssl.exe genrsa -out rsa4096-keypair.pem 4096; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "rsaKeyImport" -d "2" -c "sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate" --in=rsa4096-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? echo "=== Get public key of imported key" yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM --out pubkey_imported.pem; CheckExitStatus -ECode $? echo "=== Signing with generated key and" echo "===== rsa-pkcs1-sha1" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha1 --in data.txt --out data.4096pkcs1sha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha256" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha256 --in data.txt --out data.4096pkcs1sha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha384" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha384 --in data.txt --out data.4096pkcs1sha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha512" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha512 --in data.txt --out data.4096pkcs1sha512.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha1" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha1 --in data.txt --out data.4096psssha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha256" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha256 --in data.txt --out data.4096psssha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha384" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha384 --in data.txt --out data.4096psssha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha512" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha512 --in data.txt --out data.4096psssha512.sig; CheckExitStatus -ECode $? echo "=== Signing with imported key and" echo "===== rsa-pkcs1-sha1" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha1 --in data.txt --out data.4096pkcs1sha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha256" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha256 --in data.txt --out data.4096pkcs1sha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha384" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha384 --in data.txt --out data.4096pkcs1sha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha512" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha512 --in data.txt --out data.4096pkcs1sha512.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha1" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha1 --in data.txt --out data.4096psssha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha256" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha256 --in data.txt --out data.4096psssha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha384" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha384 --in data.txt --out data.4096psssha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha512" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha512 --in data.txt --out data.4096psssha512.sig; CheckExitStatus -ECode $? echo "=== Make self signed certificate" #yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? #yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? echo "=== Sign attestation certificate" yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? <# echo "=== Decrypt with generated key and PKCS1v15" openssl.exe rsautl -encrypt -inkey pubkey.pem -pubin -in data.txt -out data.enc yubihsm-shell.exe -p password -a decrypt-pkcs1v15 -i $keyid --in data.enc --out data.dec if (@(Compare-Object $(Get-Content "data.txt") $(Get-Content "data.dec") -sync 0).length -ne 0) { echo "Decrypt failed" exit 2 } rm data.dec echo "=== Decrypt with imported key and PKCS1v15" openssl.exe rsautl -encrypt -inkey pubkey_imported.pem -pubin -in data.txt -out data.enc yubihsm-shell.exe -p password -a decrypt-pkcs1v15 -i $import_keyid --in data.enc --out data.dec if (@(Compare-Object $(Get-Content "data.txt") $(Get-Content "data.dec") -sync 0).length -ne 0) { echo "Decrypt failed" exit 2 } rm data.dec #> echo "=== Delete keys" yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? cd .. Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue Set-PSDebug -Trace 0yubihsm-shell-2.7.1/resources/tests/ps1/test_eckey.ps10000644000175100017510000010004615133003406022353 0ustar runnerrunner$ARCH=$args[0] if($ARCH -eq "x86") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files (x86)/Yubico/YubiHSM Shell/bin;C:/Users/dev/vcpkg/vcpkg-master/packages/openssl-windows_x86-windows/bin" } } elseif ($ARCH -eq "x64") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files/Yubico/YubiHSM Shell/bin;C:/Users/dev/vcpkg/vcpkg-master/packages/openssl-windows_x64-windows/bin" } } else { echo "Usage: ./cmdline_test.ps1 " echo "" echo "This is a test script that uses the yubihsm-shell command line tool to reset the conncted YubiHSM and then different commands." echo "" echo " x86 expects that yubihsm-shell.exe is installed in 'C:/Program Files (x86)/Yubico/Yubico PIV Tool/bin'" echo " x64 expects that yubhsm-shell.exe is installed in 'C:/Program Files/Yubico/Yubico PIV Tool/bin'" exit } $env:Path += ";C:\Users\dev\vcpkg\vcpkg-master\packages\openssl-windows_x64-windows\tools\openssl" echo "Running commands on $ARCH architecture" $TEST_DIR = "yubihsm-shell_test_dir" Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue New-Item $TEST_DIR -type Directory -Force cd $TEST_DIR echo "test signing data" > data.txt Set-PSDebug -Trace 1 $ErrorActionPreference = "Stop" function CheckExitStatus { param ( $ECode ) if(!$ECode) { echo "Fail!" exit } } $keyid=100 $import_keyid=200 echo "---------------------- EC keys --------------------- " # ECP224 echo "**********************************" echo " ECP224" echo "**********************************" #-- Generate yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "ecKey" -d "5,8,13" -c "sign-ecdsa,derive-ecdh,sign-attestation-certificate" -A "ecp224"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t asymmetric-key > info.txt; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "id: 0x0064"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "type: asymmetric-key"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "algorithm: ec224df"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern 'label: "ecKey"'; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "domains: 5:8:13"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "origin: generated"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "capabilities: derive-ecdh:sign-attestation-certificate:sign-ecdsa"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Import openssl.exe ecparam -genkey -name secp224r1 -noout -out secp224r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "ecKeyImport" -d "2,6,7" -c "sign-ecdsa,sign-attestation-certificate" --in=secp224r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM; CheckExitStatus -ECode $? # -- Sign yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt > data.ecp224sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt > data.ecp224sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt > data.ecp224sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt > data.ecp224sha512.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt > data.ecp224sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt > data.ecp224sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt > data.ecp224sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt > data.ecp224sha512.sig; CheckExitStatus -ECode $? #-- Get attestation certificate and a selfsigned certificate yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? rm selfsigned_cert.pem #-- Sign attestation certificate yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? #-- Derive ECDH openssl.exe ec -in secp224r1-keypair.pem -pubout -out secp224r1-pubkey.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a derive-ecdh -i $keyid --in secp224r1-pubkey.pem; CheckExitStatus -ECode $? #-- Delete yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t opaque; CheckExitStatus -ECode $? echo "**********************************" echo " ECP256" echo "**********************************" # ECP256 #-- Generate yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "ecKey" -d "5,8,13" -c "sign-ecdsa,derive-ecdh,sign-attestation-certificate" -A "ecp256"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Import openssl.exe ecparam -genkey -name secp256r1 -noout -out secp256r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "ecKeyImport" -d "1,2,3,4,5" -c "sign-ecdsa,sign-attestation-certificate" --in=secp256r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Sign yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt > data.ecp256sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt > data.ecp256sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt > data.ecp256sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt > data.ecp256sha512.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt > data.ecp256sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt > data.ecp256sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt > data.ecp256sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt > data.ecp256sha512.sig; CheckExitStatus -ECode $? #-- Get attestation certificate and a selfsigned certificate yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? rm selfsigned_cert.pem #-- Sign attestation certificate yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? #-- Derive ECDH openssl.exe ec -in secp256r1-keypair.pem -pubout -out secp256r1-pubkey.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a derive-ecdh -i $keyid --in secp256r1-pubkey.pem; CheckExitStatus -ECode $? #-- Delete yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t opaque; CheckExitStatus -ECode $? echo "**********************************" echo " ECP384" echo "**********************************" # ECP384 #-- Generate yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "ecKey" -d "5,8,13" -c "sign-ecdsa,derive-ecdh,sign-attestation-certificate" -A "ecp384"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Import openssl.exe ecparam -genkey -name secp384r1 -noout -out secp384r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "ecKeyImport" -d "1,2,3,4,5" -c "sign-ecdsa,sign-attestation-certificate" --in=secp384r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Sign yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt > data.ecp384sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt > data.ecp384sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt > data.ecp384sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt > data.ecp384sha512.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt > data.ecp384sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt > data.ecp384sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt > data.ecp384sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt > data.ecp384sha512.sig; CheckExitStatus -ECode $? #-- Get attestation certificate and a selfsigned certificate yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? rm selfsigned_cert.pem #-- Sign attestation certificate yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? #-- Derive ECDH openssl.exe ec -in secp384r1-keypair.pem -pubout -out secp384r1-pubkey.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a derive-ecdh -i $keyid --in secp384r1-pubkey.pem; CheckExitStatus -ECode $? #-- Delete yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t opaque; CheckExitStatus -ECode $? echo "**********************************" echo " ECP512" echo "**********************************" # ECP512 #-- Generate yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "ecKey" -d "5,8,13" -c "sign-ecdsa,derive-ecdh,sign-attestation-certificate" -A "ecp521"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Import openssl ecparam -genkey -name secp521r1 -noout -out secp521r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "ecKeyImport" -d "1,2,3,4,5" -c "sign-ecdsa,sign-attestation-certificate" --in=secp521r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Sign yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt > data.ecp521sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt > data.ecp521sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt > data.ecp521sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt > data.ecp521sha512.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt > data.ecp521sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt > data.ecp521sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt > data.ecp521sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt > data.ecp521sha512.sig; CheckExitStatus -ECode $? #-- Get attestation certificate and a selfsigned certificate yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? rm selfsigned_cert.pem #-- Sign attestation certificate yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? #-- Derive ECDH openssl.exe ec -in secp521r1-keypair.pem -pubout -out secp521r1-pubkey.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a derive-ecdh -i $keyid --in secp521r1-pubkey.pem; CheckExitStatus -ECode $? #-- Delete yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t opaque; CheckExitStatus -ECode $? echo "**********************************" echo " ECK256" echo "**********************************" # ECK256 #-- Generate yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "ecKey" -d "5,8,13" -c "sign-ecdsa,derive-ecdh,sign-attestation-certificate" -A "eck256"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Import openssl.exe ecparam -genkey -name secp256k1 -noout -out secp256k1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "ecKeyImport" -d "1,2,3,4,5" -c "sign-ecdsa,sign-attestation-certificate" --in=secp256k1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Sign yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt > data.eck256sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt > data.eck256sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt > data.eck256sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt > data.eck256sha512.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt > data.eck256sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt > data.eck256sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt > data.eck256sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt > data.eck256sha512.sig; CheckExitStatus -ECode $? #-- Get attestation certificate and a selfsigned certificate yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? rm selfsigned_cert.pem #-- Sign attestation certificate yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? #-- Derive ECDH openssl.exe ec -in secp256k1-keypair.pem -pubout -out secp256k1-pubkey.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a derive-ecdh -i $keyid --in secp256k1-pubkey.pem; CheckExitStatus -ECode $? #-- Delete yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t opaque; CheckExitStatus -ECode $? echo "**********************************" echo " Brainpool256" echo "**********************************" # Brainpool256 #-- Generate yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "ecKey" -d "5,8,13" -c "sign-ecdsa,derive-ecdh,sign-attestation-certificate" -A "ecbp256"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Import openssl.exe ecparam -genkey -name brainpoolP256r1 -noout -out brainpool256r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "ecKeyImport" -d "1,2,3,4,5" -c "sign-ecdsa,sign-attestation-certificate" --in=brainpool256r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Sign yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt > data.ecbp256sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt > data.ecbp256sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt > data.ecbp256sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt > data.ecbp256sha512.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt > data.ecbp256sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt > data.ecbp256sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt > data.ecbp256sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt > data.ecbp256sha512.sig; CheckExitStatus -ECode $? #-- Get attestation certificate and a selfsigned certificate yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? rm selfsigned_cert.pem #-- Sign attestation certificate yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? #-- Derive ECDH openssl.exe ec -in brainpool256r1-keypair.pem -pubout -out brainpool256r1-pubkey.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a derive-ecdh -i $keyid --in brainpool256r1-pubkey.pem; CheckExitStatus -ECode $? #-- Delete yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t opaque; CheckExitStatus -ECode $? echo "**********************************" echo " Brainpool384" echo "**********************************" # Brainpool384 #-- Generate yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "ecKey" -d "5,8,13" -c "sign-ecdsa,derive-ecdh,sign-attestation-certificate" -A "ecbp384"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Import openssl.exe ecparam -genkey -name brainpoolP384r1 -noout -out brainpool384r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "ecKeyImport" -d "1,2,3,4,5" -c "sign-ecdsa,sign-attestation-certificate" --in=brainpool384r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Sign yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt > data.ecbp384sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt > data.ecbp384sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt > data.ecbp384sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt > data.ecbp384sha512.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt > data.ecbp384sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt > data.ecbp384sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt > data.ecbp384sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt > data.ecbp384sha512.sig; CheckExitStatus -ECode $? #-- Get attestation certificate and a selfsigned certificate yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? rm selfsigned_cert.pem #-- Sign attestation certificate yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? #-- Derive ECDH openssl.exe ec -in brainpool384r1-keypair.pem -pubout -out brainpool384r1-pubkey.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a derive-ecdh -i $keyid --in brainpool384r1-pubkey.pem; CheckExitStatus -ECode $? #-- Delete yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t opaque; CheckExitStatus -ECode $? echo "**********************************" echo " Brainpool512" echo "**********************************" # Brainpool512 #-- Generate yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "ecKey" -d "5,8,13" -c "sign-ecdsa,derive-ecdh,sign-attestation-certificate" -A "ecbp512"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Import openssl.exe ecparam -genkey -name brainpoolP512r1 -noout -out brainpool512r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "ecKeyImport" -d "1,2,3,4,5" -c "sign-ecdsa,sign-attestation-certificate" --in=brainpool512r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Sign yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt > data.ecbp512sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt > data.ecbp512sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt > data.ecbp512sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt > data.ecbp512sha512.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt > data.ecbp512sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt > data.ecbp512sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt > data.ecbp512sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt > data.ecbp512sha512.sig; CheckExitStatus -ECode $? #-- Get attestation certificate and a selfsigned certificate yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? rm selfsigned_cert.pem #-- Sign attestation certificate yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? #-- Derive ECDH openssl.exe ec -in brainpool512r1-keypair.pem -pubout -out brainpool512r1-pubkey.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a derive-ecdh -i $keyid --in brainpool512r1-pubkey.pem; CheckExitStatus -ECode $? #-- Delete yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t opaque; CheckExitStatus -ECode $? cd .. Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue Set-PSDebug -Trace 0yubihsm-shell-2.7.1/resources/tests/bash/0000755000175100017510000000000015133003406020000 5ustar runnerrunneryubihsm-shell-2.7.1/resources/tests/bash/test_edkey.sh0000755000175100017510000000553615133003406022510 0ustar runnerrunner#!/bin/bash set -u if [ "$#" -ne 1 ]; then BIN="yubihsm-shell" else BIN=$1 # path to the yubico-piv-tool command line tool fi if [ -e yubihsm-shell_test_dir ]; then rm -rf yubihsm-shell_test_dir fi mkdir yubihsm-shell_test_dir; cd yubihsm-shell_test_dir echo test signing data > data.txt test () { set +e $1 > output.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat output.txt rm output.txt exit 1 else echo "$2 ... OK!" rm output.txt fi set -e } set -e echo "====================== ED keys ===================== " # Generate echo "Generate key:" test "$BIN -p password -a generate-asymmetric-key -i 100 -l \"edKey\" -d 1,2,3 -c sign-eddsa -A ed25519" " Generate key" test "$BIN -p password -a get-object-info -i 100 -t asymmetric-key" " get-object-info" info=$($BIN -p password -a get-object-info -i 100 -t asymmetric-key 2>&1) test "echo $info | grep \"id: 0x0064\"" " Object info contains correct ID" test "echo $info | grep \"type: asymmetric-key\"" " Object info contains correct type" test "echo $info | grep \"algorithm: ed25519\"" " Object info contains correct algorithm" test "echo $info | grep 'label: \"edKey\"'" " Object info contains correct label" test "echo $info | grep \"domains: 1:2:3\"" " Object info contains correct domains" test "echo $info | grep \"origin: generated\"" " Object info contains correct origin" test "echo $info | grep \"capabilities: sign-eddsa\"" " Object info contains correct capabilities" # Import #ssh-keygen -t ed25519 -C "test@yubihsm.se" -f edkey -N foo123 #$BIN --verbose=5 -p password -a put-asymmetric-key -i 200 -l "edKey_imported" -d "5" -c "sign-eddsa" --in=edkey # Get public key echo "Get public key:" test "$BIN -p password -a get-public-key -i 100" " Get public key to stdout" $BIN -p password -a get-public-key -i 100 > edkey1.pub 2>/dev/null test "$BIN -p password -a get-public-key -i 100 --out edkey2.pub" " Get public key to file" test "cmp edkey1.pub edkey2.pub" " Match public key in stdout and file" # Signing echo "Signing:" test "$BIN -p password -a sign-eddsa -i 100 -A ed25519 --in data.txt" " Sign to stdout" $BIN -p password -a sign-eddsa -i 100 -A ed25519 --in data.txt > data.ed1.sig 2>/dev/null test "$BIN -p password -a sign-eddsa -i 100 -A ed25519 --in data.txt --out data.ed2.sig" " Sign to file" if [[ $(cat data.ed1.sig) != $(cat data.ed2.sig) ]]; then echo "Signature in stdout and file are different" exit 2 fi echo " Matching signature in stdout and file ... OK" # Generating CSR echo "Generating CSR:" test "$BIN -p password -a generate-csr -i 100 -S /CN=test/ --out csr.pem" " Generate CSR with yubihsm-shell" test "openssl req -in csr.pem -verify" " Verify CSR with openssl" # Delete echo "Clean up:" test "$BIN -p password -a delete-object -i 100 -t asymmetric-key" " Delete key" cd .. rm -rf yubihsm-shell_test_dir set +e yubihsm-shell-2.7.1/resources/tests/bash/template.dat0000644000175100017510000000060415133003406022305 0ustar runnerrunnerAQABCQIBAM3enEjbk5aw6JEezWDROOKvcLCmKB7kDPMn6IuLEUi7KsOjvetQJgD5kfRVwxYxCCAKlReTUvJFwg7gI5h3bF/xQF+FNZ2yojQ1rpvAAHvK8BROu6G6mlY4ZhzhzHDp6+8lUNDz5ljw2PTeGPj1T46MX3dY4r8OSljdsIn/IeVQoobriOF6cVXL5GGoLHzbqtr3jegM2WmrKUJjhKSEJL0WoAWRTYp+WeObMTlihZOM6KYYukQYE900K+YO3nnkEUHiQRDgYGTPNnUOXiGk5wcxk9xqHIHPUyzjdgwiP6/rWMCJ5fMc/EmyEBRFc1+sw1oZiT6cpJeqLHC0ocNKWB8DAAIACgQABAAAASwFAAQAAIygBgAFcm9vdAA=yubihsm-shell-2.7.1/resources/tests/bash/opensc_test.bats0000644000175100017510000005774615133003406023224 0ustar runnerrunnerload 'test_helper/bats-support/load' load 'test_helper/bats-assert/load' setup_file() { echo "--- Configuration via Environment Variables ---" >&3 echo "MODULE: Path to the PKCS#11 module, default /usr/local/lib/yubihsm_pkcs11.so (Linux) or /usr/local/lib/yubihsm_pkcs11.dylib (Mac)" >&3 echo "EDIT_PATH: (Windows/Msys only) Path to directory where pkcs11-tool.exe and libyubihsm is located if not in default locations. Use delimiter ":". Example: export EDIT_PATH='C:\Path\To\OpenSC\tools:C:\Path\To\YubiHSM Shell\bin" >&3 echo "CONFIG_FILE: Path to the yubihsm_pkcs11 configuration file, default is in current directory" >&3 echo "-----------------------------------------------" >&3 echo "" >&3 export EC_CURVES="secp224r1 secp256r1 secp384r1 secp521r1 secp256k1" export pkcs11="pkcs11-tool" export RSA_LENGTHS="2048 3072 4096" export YUBIHSM_PKCS11_CONF=${CONFIG_FILE:-"$(pwd)/yubihsm_pkcs11.conf"} local default_module_path="/usr/local/lib/yubihsm_pkcs11.dylib" #Default path for Mac os=$(uname -o) if ! { [[ "$os" == "Linux" ]] && grep -q 'Fedora' /etc/os-release 2>/dev/null; }; then EC_CURVES="$EC_CURVES brainpoolP256r1 brainpoolP384r1 brainpoolP512r1" fi if [[ "$os" == "Msys" ]]; then echo "This script expects that the pkcs11-tool from OpenSC is installed under "C:\Program Files\OpenSC Project\OpenSC\tools" and that libyubihsm.dll is installed under "C:\Program Files\Yubico\YubiHSM Shell\bin" " echo "If that is not the case, please point to the correct locations via the environment variable EDIT_PATH" pkcs11="pkcs11-tool.exe" default_module_path="C:\Program Files\Yubico\YubiHSM Shell\bin\pkcs11\yubihsm_pkcs11.dll" export MSYS2_ARG_CONV_EXCL=* if ! [ -z "$EDIT_PATH" ]; then export PATH="$PATH:"$EDIT_PATH"" else # Adds pkcs11-tool and yubihsm-shell to PATH export PATH="$PATH:C:\Program Files\OpenSC Project\OpenSC\tools:C:\Program Files\Yubico\YubiHSM Shell\bin" fi elif [[ "$os" == "GNU/LINUX" ]]; then default_module_path="/usr/local/lib/yubihsm_pkcs11.so" fi export MODULE=${MODULE:-$default_module_path} echo "--------------------------------" >&3 echo "Variables Check:" >&3 echo "Using module: "$MODULE"" >&3 echo "Using pkcs11: "$pkcs11"" >&3 echo "EC Curves to test: "$EC_CURVES"" >&3 echo "RSA Lengths to test: "$RSA_LENGTHS"" >&3 echo "--------------------------------" >&3 echo "These tests will reset your HSM" >&3 echo "Press Enter to continue or Ctrl-C + enter to abort" >&3 read -p "" if [ -e yubihsm-shell_test_dir ]; then rm -rf yubihsm-shell_test_dir fi mkdir yubihsm-shell_test_dir; cd yubihsm-shell_test_dir echo "test signing data" > data.txt } @test "EC Curve tests" { for curve in $EC_CURVES; do echo "Testing curve: "$curve"" >&3 #Generate key run "$pkcs11" --module "$MODULE" --login --pin 0001password --keypairgen --id 1 --key-type EC:"$curve" assert_success "Generate EC key with curve $curve" run "$pkcs11" --module "$MODULE" --login --pin 0001password --read-object --id 1 --type pubkey --output-file pubkey.der assert_success "Get public key of generated key" #Sign with generated key run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 1 -m ECDSA-SHA1 --signature-format openssl -i data.txt -o data.sig assert_success "Sign with generated key and ECDSA-SHA1" run openssl dgst -sha1 -verify pubkey.der -signature data.sig data.txt assert_success "Verify signature with openssl" run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 1 -m ECDSA-SHA256 --signature-format openssl -i data.txt -o data.sig assert_success "Sign with generated key and ECDSA-SHA256" run openssl dgst -sha256 -verify pubkey.der -signature data.sig data.txt assert_success "Verify signature with openssl" run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 1 -m ECDSA-SHA384 --signature-format openssl -i data.txt -o data.sig assert_success "Sign with generated key and ECDSA-SHA384" run openssl dgst -sha384 -verify pubkey.der -signature data.sig data.txt assert_success "Verify signature with openssl" run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 1 -m ECDSA-SHA512 --signature-format openssl -i data.txt -o data.sig assert_success "Sign with generated key and ECDSA-SHA512" run openssl dgst -sha512 -verify pubkey.der -signature data.sig data.txt assert_success "Verify signature with openssl" #Import key run openssl ecparam -name "$curve" -genkey -noout -out keypair.pem assert_success "Generate keypair with curve "$curve" using openssl" run "$pkcs11" --module "$MODULE" --login --pin 0001password --write-object keypair.pem --id 2 --type privkey --usage-sign assert_success "Import EC key with curve "$curve"" run "$pkcs11" --module "$MODULE" --login --pin 0001password --read-object --id 2 --type pubkey --output-file pubkey_imported.der assert_success "Get public key of imported key" #Sign with imported key run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 2 -m ECDSA-SHA1 --signature-format openssl -i data.txt -o data.sig assert_success "Sign with imported key and ECDSA-SHA1" run openssl dgst -sha1 -verify pubkey_imported.der -signature data.sig data.txt assert_success "Verify signature with openssl" run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 2 -m ECDSA-SHA256 --signature-format openssl -i data.txt -o data.sig assert_success "Sign with imported key and ECDSA-SHA256" run openssl dgst -sha256 -verify pubkey_imported.der -signature data.sig data.txt assert_success "Verify signature with openssl" run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 2 -m ECDSA-SHA384 --signature-format openssl -i data.txt -o data.sig assert_success "Sign with imported key and ECDSA-SHA384" run openssl dgst -sha384 -verify pubkey_imported.der -signature data.sig data.txt assert_success "Verify signature with openssl" run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 2 -m ECDSA-SHA512 --signature-format openssl -i data.txt -o data.sig assert_success "Sign with imported key and ECDSA-SHA512" run openssl dgst -sha512 -verify pubkey_imported.der -signature data.sig data.txt assert_success "Verify signature with openssl" #Derive ECDH run "$pkcs11" --module "$MODULE" --login --pin 0001password --derive --id 1 --input-file pubkey_imported.der --output-file ecdh_pkcs11.bin assert_success "Derive ECDH usin pkcs11-tool" run openssl pkeyutl -derive -inkey keypair.pem -peerkey pubkey.der -out ecdh_openssl.bin assert_success "Derive ECDH using openssl" run cmp ecdh_pkcs11.bin ecdh_openssl.bin assert_success "Compare the derived ECDH keys" run rm ecdh_pkcs11.bin ecdh_openssl.bin assert_success "Delete ECDH keys" # Requires writable session? yubihs-pkcs11 only allowed regular users #run "$pkcs11" --module ""$MODULE"" --login --pin 0001password --test-ec --id 200 --key-type EC:secp256r1 # assert_success "Test EC key with yubihs-pkcs11" #Delete keys run "$pkcs11" --module "$MODULE" --login --pin 0001password --delete-object --id 1 --type privkey assert_success "Delete generated key" run "$pkcs11" --module "$MODULE" --login --pin 0001password --delete-object --id 2 --type privkey assert_success "Delete imported key" done } @test "RSA Key tests" { run openssl dgst -sha1 -binary -out data.sha1 data.txt assert_success "Hash data with SHA1 and OpenSSL" run openssl dgst -sha256 -binary -out data.sha256 data.txt assert_success "Hash data with SHA256 and OpenSSL" run openssl dgst -sha384 -binary -out data.sha384 data.txt assert_success "Hash data with SHA384 and OpenSSL" run openssl dgst -sha512 -binary -out data.sha512 data.txt assert_success "Hash data with SHA512 and OpenSSL" for length in $RSA_LENGTHS; do echo "Testing RSA key with length: "$length"" >&3 #Generate key run "$pkcs11" --module "$MODULE" --login --pin 0001password --keypairgen --id 1 --key-type rsa:"$length" --usage-sign --usage-decrypt assert_success "Generate RSA key with length "$length"" run "$pkcs11" --module "$MODULE" --login --pin 0001password --read-object --id 1 --type pubkey --output-file pubkey.der assert_success "Get public key of generated key" #Sign with generated key and RSA-PKCS run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 1 -m SHA1-RSA-PKCS -i data.txt -o data.sig assert_success "Sign with generated key and SHA1-RSA-PKCS" run openssl dgst -sha1 -verify pubkey.der -signature data.sig data.txt assert_success "Verify signature with openssl" run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 1 -m SHA256-RSA-PKCS -i data.txt -o data.sig assert_success "Sign with generated key and SHA256-RSA-PKCS" run openssl dgst -sha256 -verify pubkey.der -signature data.sig data.txt assert_success "Verify signature with openssl" run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 1 -m SHA384-RSA-PKCS -i data.txt -o data.sig assert_success "Sign with generated key and SHA384-RSA-PKCS" run openssl dgst -sha384 -verify pubkey.der -signature data.sig data.txt assert_success "Verify signature with openssl" run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 1 -m SHA512-RSA-PKCS -i data.txt -o data.sig assert_success "Sign with generated key and SHA512-RSA-PKCS" run openssl dgst -sha512 -verify pubkey.der -signature data.sig data.txt assert_success "Verify signature with openssl" #Sign with generated key and RSA-PSS run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 1 -m SHA1-RSA-PKCS-PSS -i data.txt -o data.sig assert_success "Sign with generated key and SHA1-RSA-PKCS-PSS" run openssl pkeyutl -verify -in data.sha1 -sigfile data.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey.der -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha1 assert_success "Verify signature with openssl" run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 1 -m SHA256-RSA-PKCS-PSS -i data.txt -o data.sig assert_success "Sign with generated key and SHA256-RSA-PKCS-PSS" run openssl pkeyutl -verify -in data.sha256 -sigfile data.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey.der -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha256 assert_success "Verify signature with openssl" run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 1 -m SHA384-RSA-PKCS-PSS -i data.txt -o data.sig assert_success "Sign with generated key and SHA384-RSA-PKCS-PSS" run openssl pkeyutl -verify -in data.sha384 -sigfile data.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey.der -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha384 assert_success "Verify signature with openssl" run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 1 -m SHA512-RSA-PKCS-PSS -i data.txt -o data.sig assert_success "Sign with generated key and SHA512-RSA-PKCS-PSS" run openssl pkeyutl -verify -in data.sha512 -sigfile data.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey.der -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha512 assert_success "Verify signature with openssl" #Decrypt with generated key and PKCS1v15 run openssl rsautl -encrypt -inkey pubkey.der -pubin -in data.txt -out data.enc assert_success "Encrypt with openssl using PKCS1v15" run "$pkcs11" --module "$MODULE" --decrypt --pin 0001password --id 1 -m RSA-PKCS --input-file data.enc --output-file data.dec assert_success "Decrypt using generated key" run cmp data.dec data.txt assert_success "Compare decrypted data with plain text data" run rm data.enc data.dec assert_success "Delete test data" #Decrypt with generated key and OAEP run openssl pkeyutl -encrypt -pubin -inkey pubkey.der -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha1 -pkeyopt rsa_mgf1_md:sha1 -in data.txt -out data.enc assert_success "Encrypt with OpenSSL using OAEP and SHA1" run "$pkcs11" --module "$MODULE" --decrypt --pin 0001password --id 1 -m RSA-PKCS-OAEP --hash-algorithm=SHA-1 --input-file data.enc --output-file data.dec assert_success "Decrypt using generated key with SHA1" run cmp data.dec data.txt assert_success "Compare decrypted data for SHA1" run rm data.enc data.dec assert_success "Delete test data for SHA1" run openssl pkeyutl -encrypt -pubin -inkey pubkey.der -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256 -in data.txt -out data.enc assert_success "Encrypt with OpenSSL using OAEP and SHA256" run "$pkcs11" --module "$MODULE" --decrypt --pin 0001password --id 1 -m RSA-PKCS-OAEP --hash-algorithm=SHA256 --input-file data.enc --output-file data.dec assert_success "Decrypt using generated key with SHA256" run cmp data.dec data.txt assert_success "Compare decrypted data for SHA256" run rm data.enc data.dec assert_success "Delete test data for SHA256" run openssl pkeyutl -encrypt -pubin -inkey pubkey.der -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha384 -in data.txt -out data.enc assert_success "Encrypt with OpenSSL using OAEP and SHA384" run "$pkcs11" --module "$MODULE" --decrypt --pin 0001password --id 1 -m RSA-PKCS-OAEP --hash-algorithm=SHA384 --input-file data.enc --output-file data.dec assert_success "Decrypt using generated key with SHA384" run cmp data.dec data.txt assert_success "Compare decrypted data for SHA384" run rm data.enc data.dec assert_success "Delete test data for SHA384" run openssl pkeyutl -encrypt -pubin -inkey pubkey.der -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha512 -pkeyopt rsa_mgf1_md:sha512 -in data.txt -out data.enc assert_success "Encrypt with OpenSSL using OAEP and SHA512" run "$pkcs11" --module "$MODULE" --decrypt --pin 0001password --id 1 -m RSA-PKCS-OAEP --hash-algorithm=SHA512 --input-file data.enc --output-file data.dec assert_success "Decrypt using generated key with SHA512" run cmp data.dec data.txt assert_success "Compare decrypted data for SHA512" run rm data.enc data.dec assert_success "Delete test data for SHA512" #Import key run openssl genrsa -out keypair.pem "$length" assert_success "Generate key with openssl" run "$pkcs11" --module "$MODULE" --login --pin 0001password --write-object keypair.pem --id 2 --type privkey --usage-sign --usage-decrypt assert_success "Import RSA"$length" key" run "$pkcs11" --module "$MODULE" --login --pin 0001password --read-object --id 2 --type pubkey --output-file pubkey_imported.der assert_success "Get public key of imported key" # Sign with imported key and PKCS run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 2 -m SHA1-RSA-PKCS -i data.txt -o data.sig assert_success "Sign with imported key and SHA1-RSA-PKCS" run openssl dgst -sha1 -verify pubkey_imported.der -signature data.sig data.txt assert_success "Verify signature with openssl" run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 2 -m SHA256-RSA-PKCS -i data.txt -o data.sig assert_success "Sign with imported key and SHA256-RSA-PKCS" run openssl dgst -sha256 -verify pubkey_imported.der -signature data.sig data.txt assert_success "Verify signature with openssl" run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 2 -m SHA384-RSA-PKCS -i data.txt -o data.sig assert_success "Sign with imported key and SHA384-RSA-PKCS" run openssl dgst -sha384 -verify pubkey_imported.der -signature data.sig data.txt assert_success "Verify sgnature with openssl" run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 2 -m SHA512-RSA-PKCS -i data.txt -o data.sig assert_success "Sign with imported key and SHA512-RSA-PKCS" run openssl dgst -sha512 -verify pubkey_imported.der -signature data.sig data.txt assert_success "Verify signature with openssl" # Sign with imported key and RSA-PSS run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 2 -m SHA1-RSA-PKCS-PSS -i data.txt -o data.sig assert_success "Sign with imported key and SHA1-RSA-PKCS-PSS" run openssl pkeyutl -verify -in data.sha1 -sigfile data.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_imported.der -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha1 assert_success "Verify signature with openssl" run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 2 -m SHA256-RSA-PKCS-PSS -i data.txt -o data.sig assert_success "Sign with imported key and SHA256-RSA-PKCS-PSS" run openssl pkeyutl -verify -in data.sha256 -sigfile data.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_imported.der -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha256 assert_success "Verify signature with openssl" run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 2 -m SHA384-RSA-PKCS-PSS -i data.txt -o data.sig assert_success "Sign with imported key and SHA384-RSA-PKCS-PSS" run openssl pkeyutl -verify -in data.sha384 -sigfile data.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_imported.der -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha384 assert_success "Verify signature with openssl" run "$pkcs11" --module "$MODULE" --sign --pin 0001password --id 2 -m SHA512-RSA-PKCS-PSS -i data.txt -o data.sig assert_success "Sign with imported key and SHA512-RSA-PKCS-PSS" run openssl pkeyutl -verify -in data.sha512 -sigfile data.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_imported.der -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha512 assert_success "Verify signature with openssl" # Decrypt with imported key and PKCS1v15 run openssl rsautl -encrypt -inkey pubkey_imported.der -pubin -in data.txt -out data.enc assert_success "Encryp with openssl using PKCS1v15" run "$pkcs11" --module "$MODULE" --decrypt --pin 0001password --id 2 -m RSA-PKCS --input-file data.enc --output-file data.dec assert_success "Decrypt using imported key" run cmp data.dec data.txt assert_success "Compare decrypted data with plain text data" run rm data.enc data.dec assert_success "Delete test data" # Decrypt with imported key and OAEP run openssl pkeyutl -encrypt -pubin -inkey pubkey_imported.der -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha1 -pkeyopt rsa_mgf1_md:sha1 -in data.txt -out data.enc assert_success "Encrypt with openssl using OAEP and SHA1" run openssl pkeyutl -encrypt -pubin -inkey pubkey_imported.der -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha1 -pkeyopt rsa_mgf1_md:sha1 -in data.txt -out data.enc assert_success "Encrypt with OpenSSL using OAEP and SHA1" run "$pkcs11" --module "$MODULE" --decrypt --pin 0001password --id 2 -m RSA-PKCS-OAEP --hash-algorithm=SHA-1 --input-file data.enc --output-file data.dec assert_success "Decrypt using imported key with SHA1" run cmp data.dec data.txt assert_success "Compare decrypted data for SHA1" run rm data.enc data.dec assert_success "Delete test data for SHA1" run openssl pkeyutl -encrypt -pubin -inkey pubkey_imported.der -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256 -in data.txt -out data.enc assert_success "Encrypt with OpenSSL using OAEP and SHA256" run "$pkcs11" --module "$MODULE" --decrypt --pin 0001password --id 2 -m RSA-PKCS-OAEP --hash-algorithm=SHA256 --input-file data.enc --output-file data.dec assert_success "Decrypt using imported key with SHA256" run cmp data.dec data.txt assert_success "Compare decrypted data for SHA256" run rm data.enc data.dec assert_success "Delete test data for SHA256" run openssl pkeyutl -encrypt -pubin -inkey pubkey_imported.der -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha384 -in data.txt -out data.enc assert_success "Encrypt with OpenSSL using OAEP and SHA384" run "$pkcs11" --module "$MODULE" --decrypt --pin 0001password --id 2 -m RSA-PKCS-OAEP --hash-algorithm=SHA384 --input-file data.enc --output-file data.dec assert_success "Decrypt using imported key with SHA384" run cmp data.dec data.txt assert_success "Compare decrypted data for SHA384" run rm data.enc data.dec assert_success "Delete test data for SHA384" run openssl pkeyutl -encrypt -pubin -inkey pubkey_imported.der -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha512 -pkeyopt rsa_mgf1_md:sha512 -in data.txt -out data.enc assert_success "Encrypt with OpenSSL using OAEP and SHA512" run "$pkcs11" --module "$MODULE" --decrypt --pin 0001password --id 2 -m RSA-PKCS-OAEP --hash-algorithm=SHA512 --input-file data.enc --output-file data.dec assert_success "Decrypt using imported key with SHA512" run cmp data.dec data.txt assert_success "Compare decrypted data for SHA512" run rm data.enc data.dec assert_success "Delete test data for SHA512" #Delete keys run "$pkcs11" --module "$MODULE" --login --pin 0001password --delete-object --id 1 --type privkey assert_success "Delete generated key" run "$pkcs11" --module "$MODULE" --login --pin 0001password --delete-object --id 2 --type privkey assert_success "Delete generated key" done run rm data.sha1 data.sha256 data.sha384 data.sha512 data.sig data.txt assert_success "Delete test data" run rm keypair.pem pubkey.der pubkey_imported.der assert_success "Delete key files" } @test "Compress x509 Certificate" { run openssl req -x509 -newkey rsa:4096 -out too_large_cert.der -outform DER -sha256 -days 3650 -nodes -subj '/C=01/ST=01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567/L=01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567/O=0123456789012345678901234567890123456789012345678901234567890123/OU=0123456789012345678901234567890123456789012345678901234567890123' > /dev/null 2>&1 assert_success "Generating a large certificate" run "$pkcs11" --module "$MODULE" --login --pin 0001password --write-object too_large_cert.der --id 6464 --type cert assert_success "Import large x509 certificate" run "$pkcs11" --module "$MODULE" --login --pin 0001password --read-object --id 6464 --type cert --output-file too_large_cert_out.der assert_success "Get imported certificate" run cmp too_large_cert.der too_large_cert_out.der assert_success "Compare read certificate with the one imported" run "$pkcs11" --module "$MODULE" --login --pin 0001password --delete-object --id 6464 --type cert assert_success "Delete certificate" run rm too_large_cert.der too_large_cert_out.der privkey.pem assert_success "Delete files" } yubihsm-shell-2.7.1/resources/tests/bash/test_eckey.sh0000755000175100017510000002303215133003406022476 0ustar runnerrunner#!/bin/bash set -u if [ "$#" -ne 1 ]; then BIN="yubihsm-shell" else BIN=$1 # path to the yubico-piv-tool command line tool fi if [ -e yubihsm-shell_test_dir ]; then rm -rf yubihsm-shell_test_dir fi mkdir yubihsm-shell_test_dir; cd yubihsm-shell_test_dir echo test signing data > data.txt test () { set +e $1 > output.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat output.txt rm output.txt exit 1 else echo "$2 ... OK!" rm output.txt fi set -e } test_with_resp () { set +e $1 > resp.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat resp.txt rm resp.txt exit 1 else echo "$2 ... OK!" fi set -e } set -e EC_ALGOS=("ecp224" "ecp256" "ecp384" "ecp521" "eck256") EC_CURVES=("secp224r1" "secp256r1" "secp384r1" "secp521r1" "secp256k1") set +e cat /etc/os-release | grep 'Fedora' is_fedora=$? set -e echo "====================== EC keys ===================== " if [ $is_fedora -ne 0 ]; then EC_ALGOS=(${EC_ALGOS[@]} "ecbp256" "ecbp384" "ecbp512") EC_CURVES=(${EC_CURVES[@]} "brainpoolP256r1" "brainpoolP384r1" "brainpoolP512r1") fi genkey=100 import_key=200 for i in "${!EC_ALGOS[@]}"; do algo=${EC_ALGOS[i]} curve=${EC_CURVES[i]} echo "**********************************" echo " $algo" echo "**********************************" echo "=== Generate key" test_with_resp "$BIN -p password -a generate-asymmetric-key -i $genkey -l \"ecKey\" -d 5,8,13 -c sign-ecdsa,derive-ecdh,sign-attestation-certificate -A $algo" " Generate key" test "$BIN -p password -a get-object-info -i $genkey -t asymmetric-key" " get-object-info" info=$($BIN -p password -a get-object-info -i $genkey -t asymmetric-key 2> /dev/null) test "echo $info | grep \"id: $genkey\"" " Object info contains correct ID" test "echo $info | grep \"type: asymmetric-key\"" " Object info contains correct type" test "echo $info | grep \"algorithm: $algo\"" " Object info contains correct algorithm" test "echo $info | grep 'label: \"ecKey\"'" " Object info contains correct label" test "echo $info | grep \"domains: 5:8:13\"" " Object info contains correct domains" test "echo $info | grep \"origin: generated\"" " Object info contains correct origin" test "echo $info | grep \"capabilities: derive-ecdh:sign-attestation-certificate:sign-ecdsa\"" " Object info contains correct capabilities" test "$BIN -p password -a get-public-key -i $genkey --outformat=PEM --out $algo-gen.pubkey" " Get public key" echo "=== Import Key" test "openssl ecparam -genkey -name $curve -noout -out $curve-keypair.pem" " Generate key with OpenSSL" test_with_resp "$BIN -p password -a put-asymmetric-key -i $import_key -l "ecKeyImport" -d "2,6,7" -c "sign-ecdsa,sign-attestation-certificate" --in=$curve-keypair.pem" " Import key" test "$BIN -p password -a get-object-info -i $import_key -t asymmetric-key" " get-object-info" info=$($BIN -p password -a get-object-info -i $import_key -t asymmetric-key 2> /dev/null) test "echo $info | grep \"id: $import_key\"" " Object info contains correct ID" test "echo $info | grep \"type: asymmetric-key\"" " Object info contains correct type" test "echo $info | grep \"algorithm: $algo\"" " Object info contains correct algorithm" test "echo $info | grep 'label: \"ecKeyImport\"'" " Object info contains correct label" test "echo $info | grep \"domains: 2:6:7\"" " Object info contains correct domains" test "echo $info | grep \"origin: imported\"" " Object info contains correct origin" test "echo $info | grep \"capabilities: sign-attestation-certificate:sign-ecdsa\"" " Object info contains correct capabilities" test "$BIN -p password -a get-public-key -i $import_key --outformat=PEM --out $algo-import.pubkey" " Get public key" echo "=== Signing" test "$BIN -p password -a sign-ecdsa -i $genkey -A ecdsa-sha1 --in data.txt --outformat=PEM --out data.$algo-sha1gen.sig" " Sign with generated key and ecdsa-sha1" test "openssl dgst -sha1 -verify $algo-gen.pubkey -signature data.$algo-sha1gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $genkey -A ecdsa-sha256 --in data.txt --outformat=PEM --out data.$algo-sha256gen.sig" " Sign with generated key and ecdsa-sha256" test "openssl dgst -sha256 -verify $algo-gen.pubkey -signature data.$algo-sha256gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $genkey -A ecdsa-sha384 --in data.txt --outformat=PEM --out data.$algo-sha384gen.sig" " Sign with generated key and ecdsa-sha384" test "openssl dgst -sha384 -verify $algo-gen.pubkey -signature data.$algo-sha384gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $genkey -A ecdsa-sha512 --in data.txt --outformat=PEM --out data.$algo-sha512gen.sig" " Sign with generated key and ecdsa-sha512" test "openssl dgst -sha512 -verify $algo-gen.pubkey -signature data.$algo-sha512gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_key -A ecdsa-sha1 --in data.txt --outformat=PEM --out data.$algo-sha1import.sig" " Sign with imported key and ecdsa-sha1" test "openssl dgst -sha1 -verify $algo-import.pubkey -signature data.$algo-sha1import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_key -A ecdsa-sha256 --in data.txt --outformat=PEM --out data.$algo-sha256import.sig" " Sign with imported key and ecdsa-sha256" test "openssl dgst -sha256 -verify $algo-import.pubkey -signature data.$algo-sha256import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_key -A ecdsa-sha384 --in data.txt --outformat=PEM --out data.$algo-sha384import.sig" " Sign with imported key and ecdsa-sha384" test "openssl dgst -sha384 -verify $algo-import.pubkey -signature data.$algo-sha384import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_key -A ecdsa-sha512 --in data.txt --outformat=PEM --out data.$algo-sha512import.sig" " Sign with imported key and ecdsa-sha512" test "openssl dgst -sha512 -verify $algo-import.pubkey -signature data.$algo-sha512import.sig data.txt" " Verify signature with OpenSSL" echo "=== Get attestation certificate and a selfsigned certificate" set +e $BIN -p password -a sign-attestation-certificate -i $genkey --attestation-id 0 2>&1 > /dev/null # Some YubiHSMs does not have default attestation certificate def_attestation=$? set -e if [ $def_attestation -eq 0 ]; then test "$BIN -p password -a sign-attestation-certificate -i $genkey --attestation-id 0 --out cert.pem" " Sign attestation cert with default key" test "openssl x509 -in cert.pem -out cert.der -outform DER" " Convert cert format" test "$BIN -p password -a put-opaque -i $genkey -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_key -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as imported key)" test "rm cert.der" " Cleaning up" else test "$BIN -p password -a put-opaque -i $genkey -l template_cert_gen -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_key -l template_cert_imp -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as imported key)" fi test "$BIN -p password -a sign-attestation-certificate -i $genkey --attestation-id=$genkey --out selfsigned_cert.pem" " Sign attestation with same key (aka. get selfsigned cert)" test "$BIN -p password -a delete-object -i $genkey -t opaque" " Delete template cert" test "$BIN -p password -a put-opaque -i $genkey -l java_cert -A opaque-x509-certificate --informat=PEM --in selfsigned_cert.pem" " Import selfsigned cert with same key ID" test "rm selfsigned_cert.pem" " Cleaning up" #-- Sign attestation certificate test "$BIN -p password -a sign-attestation-certificate -i $genkey --attestation-id=$import_key --out selfsigned_cert.pem" " Sign attestation cert with imported key" test "$BIN -p password -a delete-object -i $genkey -t opaque" " Delete template cert" test "$BIN -p password -a delete-object -i $import_key -t opaque" " Delete template cert" test "rm selfsigned_cert.pem" " Cleaning up" echo "=== Derive ECDH:" test "openssl ec -in $curve-keypair.pem -pubout -out $curve-pubkey.pem" " Get imported key public key with OpenSSL" test "$BIN -p password -a derive-ecdh -i $genkey --in $curve-pubkey.pem --outformat binary --out $algo-ecdh-shell.key" " Derive ECDH using yubihsm-shell" test "openssl pkeyutl -derive -inkey $curve-keypair.pem -peerkey $algo-gen.pubkey -out $algo-ecdh-openssl.key" " Derive ECDH using OpenSSL" test "cmp $algo-ecdh-openssl.key $algo-ecdh-shell.key" " Compare ECDH value from yubihsm-shell and OpenSSL" echo "=== Make PKCS10 Certificate Signing Request:" test "$BIN -p password -a generate-csr -i $genkey -S /CN=test/ --out csr.pem" " Generate CSR with yubihsm-shell" test "openssl req -in csr.pem -verify" " Verify CSR with openssl" test "rm csr.pem" " Clean up" echo "=== Clean up:" test "$BIN -p password -a delete-object -i $genkey -t asymmetric-key" " Delete generated key" test "$BIN -p password -a delete-object -i $import_key -t asymmetric-key" " Delete imported key" doneyubihsm-shell-2.7.1/resources/tests/bash/opensc_test.sh0000755000175100017510000004620515133003406022674 0ustar runnerrunner#!/bin/bash if [ "$#" -ne 1 ]; then echo "Usage: ./opensc_test.sh " echo "" echo "This script expects that YUBIHSM_PKCS11_CONF environment variable is defined" exit fi MODULE=$1 #$env:YUBIHSM_PKCS11_CONF=$YHPKCS11CFG test () { set +e $1 > output.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat output.txt rm output.txt exit 1 else echo "$2 ... OK!" rm output.txt fi set -e } set -e echo "this is test data" > data.txt ### Note about pkcs11-tool and object id: ### When generating/importing private keys, an ID has to be specified otherwise, practically a random key will be used ### when, for example, signing. This is because pkcs11-tool, unless a specific ID is set in the command line, it will use ### the first private key it finds to perform the operation. Setting/using a key's label/alias will not have an effect ### because it will not look for a key by label/alias. However, specifying an object to delete by its label/alias seems ### to work just fine. EC_CURVES=("secp224r1" "secp256r1" "secp384r1" "secp521r1" "secp256k1") set +e cat /etc/os-release | grep 'Fedora' is_fedora=$? set -e if [ $is_fedora -ne 0 ]; then EC_CURVES=(${EC_CURVES[@]} "brainpoolP256r1" "brainpoolP384r1" "brainpoolP512r1") fi for curve in "${EC_CURVES[@]}"; do echo "**********************************" echo " $curve" echo "**********************************" # # Generate key test "pkcs11-tool --module $MODULE --login --pin 0001password --keypairgen --id 1 --key-type EC:$curve" " Generate EC key with curve $curve" test "pkcs11-tool --module $MODULE --login --pin 0001password --read-object --id 1 --type pubkey --output-file pubkey.der" " Get public key of generated key" # Sign with generated key test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 1 -m ECDSA-SHA1 --signature-format openssl -i data.txt -o data.sig" " Sign with generated key and ECDSA-SHA1" test "openssl dgst -sha1 -verify pubkey.der -signature data.sig data.txt" " Verify signature with OpenSSL" test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 1 -m ECDSA-SHA256 --signature-format openssl -i data.txt -o data.sig" " Sign with generated key and ECDSA-SHA256" test "openssl dgst -sha256 -verify pubkey.der -signature data.sig data.txt" " Verify signature with OpenSSL" test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 1 -m ECDSA-SHA384 --signature-format openssl -i data.txt -o data.sig" " Sign with generated key and ECDSA-SHA384" test "openssl dgst -sha384 -verify pubkey.der -signature data.sig data.txt" " Verify signature with OpenSSL" test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 1 -m ECDSA-SHA512 --signature-format openssl -i data.txt -o data.sig" " Sign with generated key and ECDSA-SHA512" test "openssl dgst -sha512 -verify pubkey.der -signature data.sig data.txt" " Verify signature with OpenSSL" # Import key test "openssl ecparam -genkey -name $curve -noout -out keypair.pem" " Generate keypair with curve $curve using OpenSSL" test "pkcs11-tool --module $MODULE --login --pin 0001password --write-object keypair.pem --id 2 --type privkey --usage-sign" " Import EC key with curve $curve" test "pkcs11-tool --module $MODULE --login --pin 0001password --read-object --id 2 --type pubkey --output-file pubkey_imported.der" " Get public key of imported key" # Sign with imported key test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 2 -m ECDSA-SHA1 --signature-format openssl -i data.txt -o data.sig" " Sign with imported key and ECDSA-SHA1" test "openssl dgst -sha1 -verify pubkey_imported.der -signature data.sig data.txt" " Verify signature with OpenSSL" test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 2 -m ECDSA-SHA256 --signature-format openssl -i data.txt -o data.sig" " Sign with imported key and ECDSA-SHA256" test "openssl dgst -sha256 -verify pubkey_imported.der -signature data.sig data.txt" " Verify signature with OpenSSL" test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 2 -m ECDSA-SHA384 --signature-format openssl -i data.txt -o data.sig" " Sign with imported key and ECDSA-SHA384" test "openssl dgst -sha384 -verify pubkey_imported.der -signature data.sig data.txt" " Verify signature with OpenSSL" test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 2 -m ECDSA-SHA512 --signature-format openssl -i data.txt -o data.sig" " Sign with imported key and ECDSA-SHA512" test "openssl dgst -sha512 -verify pubkey_imported.der -signature data.sig data.txt" " Verify signature with OpenSSL" # Derive ECDH test "pkcs11-tool --module $MODULE --login --pin 0001password --derive --id 1 --input-file pubkey_imported.der --output-file ecdh_pkcs11.bin" " Derive ECDH using pkcs11-tool" test "openssl pkeyutl -derive -inkey keypair.pem -peerkey pubkey.der -out ecdh_openssl.bin" " Derive ECDH using OpenSSL" test "cmp ecdh_pkcs11.bin ecdh_openssl.bin" " Compare the derived ECDH keys" test "rm ecdh_pkcs11.bin ecdh_openssl.bin" " Delete ecdh keys" # Requires writable session? yubihsm-pkcs11 only allowed regular users #pkcs11-tool --module $MODULE --login --pin 0001password --test-ec --id 200 --key-type EC:secp256r1 # Delete keys test "pkcs11-tool --module $MODULE --login --pin 0001password --delete-object --id 1 --type privkey" " Delete generated key" test "pkcs11-tool --module $MODULE --login --pin 0001password --delete-object --id 2 --type privkey" " Delete imported key" done RSA_LENGTHS=("2048" "3072" "4096") test "openssl dgst -sha1 -binary -out data.sha1 data.txt" " Hash data with SHA1 and OpenSSL" test "openssl dgst -sha256 -binary -out data.sha256 data.txt" " Hash data with SHA256 and OpenSSL" test "openssl dgst -sha384 -binary -out data.sha384 data.txt" " Hash data with SHA384 and OpenSSL" test "openssl dgst -sha512 -binary -out data.sha512 data.txt" " Hash data with SHA512 and OpenSSL" for len in "${RSA_LENGTHS[@]}"; do echo "**********************************" echo " RSA$len" echo "**********************************" # Generate key test "pkcs11-tool --module $MODULE --login --pin 0001password --keypairgen --id 1 --key-type rsa:$len --usage-sign --usage-decrypt" " Generate RSA$len key" test "pkcs11-tool --module $MODULE --login --pin 0001password --read-object --id 1 --type pubkey --output-file pubkey.der" " Get public key of generated key" # Sign with generated key and RSA-PKCS test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 1 -m SHA1-RSA-PKCS -i data.txt -o data.sig" " Sign with generated key and SHA1-RSA-PKCS" test "openssl dgst -sha1 -verify pubkey.der -signature data.sig data.txt" " Verify signature with OpenSSL" test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 1 -m SHA256-RSA-PKCS -i data.txt -o data.sig" " Sign with generated key and SHA256-RSA-PKCS" test "openssl dgst -sha256 -verify pubkey.der -signature data.sig data.txt" " Verify signature with OpenSSL" test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 1 -m SHA384-RSA-PKCS -i data.txt -o data.sig" " Sign with generated key and SHA384-RSA-PKCS" test "openssl dgst -sha384 -verify pubkey.der -signature data.sig data.txt" " Verify signature with OpenSSL" test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 1 -m SHA512-RSA-PKCS -i data.txt -o data.sig" " Sign with generated key and SHA512-RSA-PKCS" test "openssl dgst -sha512 -verify pubkey.der -signature data.sig data.txt" " Verify signature with OpenSSL" # Sign with generated key and RSA-PSS test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 1 -m SHA1-RSA-PKCS-PSS -i data.txt -o data.sig" " Sign with generated key and SHA1-RSA-PKCS-PSS" test "openssl pkeyutl -verify -in data.sha1 -sigfile data.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey.der -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha1" " Verify signature with OpenSSL" test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 1 -m SHA256-RSA-PKCS-PSS -i data.txt -o data.sig" " Sign with generated key and SHA256-RSA-PKCS-PSS" test "openssl pkeyutl -verify -in data.sha256 -sigfile data.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey.der -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha256" " Verify signature with OpenSSL" test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 1 -m SHA384-RSA-PKCS-PSS -i data.txt -o data.sig" " Sign with generated key and SHA384-RSA-PKCS-PSS" test "openssl pkeyutl -verify -in data.sha384 -sigfile data.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey.der -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha384" " Verify signature with OpenSSL" test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 1 -m SHA512-RSA-PKCS-PSS -i data.txt -o data.sig" " Sign with generated key and SHA512-RSA-PKCS-PSS" test "openssl pkeyutl -verify -in data.sha512 -sigfile data.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey.der -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha512" " Verify signature with OpenSSL" # Decrypt with generated key and PKCS1v15 test "openssl rsautl -encrypt -inkey pubkey.der -pubin -in data.txt -out data.enc" " Encryp with OpenSSL using PKCS1v15" test "pkcs11-tool --module $MODULE --decrypt --pin 0001password --id 1 -m RSA-PKCS --input-file data.enc --output-file data.dec" " Decrypt using generated key" test "cmp data.dec data.txt" " Compare decrypted data with plain text data" test "rm data.enc data.dec" " Delete test data" # Decrypt with generated key and OAEP test "openssl pkeyutl -encrypt -pubin -inkey pubkey.der -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha1 -pkeyopt rsa_mgf1_md:sha1 -in data.txt -out data.enc" " Encrypt with OpenSSL using OAEP and SHA1" test "pkcs11-tool --module $MODULE --decrypt --pin 0001password --id 1 -m RSA-PKCS-OAEP --hash-algorithm=SHA-1 --input-file data.enc --output-file data.dec" " Decrypt using generated key" test "cmp data.dec data.txt" " Compare decrypted data with plain text data" test "rm data.enc data.dec" " Delete test data" test "openssl pkeyutl -encrypt -pubin -inkey pubkey.der -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256 -in data.txt -out data.enc" " Encrypt with OpenSSL using OAEP and SHA256" test "pkcs11-tool --module $MODULE --decrypt --pin 0001password --id 1 -m RSA-PKCS-OAEP --hash-algorithm=SHA256 --input-file data.enc --output-file data.dec" " Decrypt using generated key" test "cmp data.dec data.txt" " Compare decrypted data with plain text data" test "rm data.enc data.dec" " Delete test data" test "openssl pkeyutl -encrypt -pubin -inkey pubkey.der -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha384 -in data.txt -out data.enc" " Encrypt with OpenSSL using OAEP and SHA384" test "pkcs11-tool --module $MODULE --decrypt --pin 0001password --id 1 -m RSA-PKCS-OAEP --hash-algorithm=SHA384 --input-file data.enc --output-file data.dec" " Decrypt using generated key" test "cmp data.dec data.txt" " Compare decrypted data with plain text data" test "rm data.enc data.dec" " Delete test data" test "openssl pkeyutl -encrypt -pubin -inkey pubkey.der -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha512 -pkeyopt rsa_mgf1_md:sha512 -in data.txt -out data.enc" " Encrypt with OpenSSL using OAEP and SHA512" test "pkcs11-tool --module $MODULE --decrypt --pin 0001password --id 1 -m RSA-PKCS-OAEP --hash-algorithm=SHA512 --input-file data.enc --output-file data.dec" " Decrypt using generated key" test "cmp data.dec data.txt" " Compare decrypted data with plain text data" test "rm data.enc data.dec" " Delete test data" # Import key test "openssl genrsa -out keypair.pem $len" " Generate key with OpenSSL" test "pkcs11-tool --module $MODULE --login --pin 0001password --write-object keypair.pem --id 2 --type privkey --usage-sign --usage-decrypt" " Import RSA$len key" test "pkcs11-tool --module $MODULE --login --pin 0001password --read-object --id 2 --type pubkey --output-file pubkey_imported.der" " Get public key of imported key" # Sign with imported key and PKCS test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 2 -m SHA1-RSA-PKCS -i data.txt -o data.sig" " Sign with imported key and SHA1-RSA-PKCS" test "openssl dgst -sha1 -verify pubkey_imported.der -signature data.sig data.txt" " Verify signature with OpenSSL" test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 2 -m SHA256-RSA-PKCS -i data.txt -o data.sig" " Sign with imported key and SHA256-RSA-PKCS" test "openssl dgst -sha256 -verify pubkey_imported.der -signature data.sig data.txt" " Verify signature with OpenSSL" test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 2 -m SHA384-RSA-PKCS -i data.txt -o data.sig" " Sign with imported key and SHA384-RSA-PKCS" test "openssl dgst -sha384 -verify pubkey_imported.der -signature data.sig data.txt" " Verify signature with OpenSSL" test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 2 -m SHA512-RSA-PKCS -i data.txt -o data.sig" " Sign with imported key and SHA512-RSA-PKCS" test "openssl dgst -sha512 -verify pubkey_imported.der -signature data.sig data.txt" " Verify signature with OpenSSL" # Sign with imported key and RSA-PSS test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 2 -m SHA1-RSA-PKCS-PSS -i data.txt -o data.sig" " Sign with imported key and SHA1-RSA-PKCS-PSS" test "openssl pkeyutl -verify -in data.sha1 -sigfile data.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_imported.der -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha1" " Verify signature with OpenSSL" test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 2 -m SHA256-RSA-PKCS-PSS -i data.txt -o data.sig" " Sign with imported key and SHA256-RSA-PKCS-PSS" test "openssl pkeyutl -verify -in data.sha256 -sigfile data.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_imported.der -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha256" " Verify signature with OpenSSL" test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 2 -m SHA384-RSA-PKCS-PSS -i data.txt -o data.sig" " Sign with imported key and SHA384-RSA-PKCS-PSS" test "openssl pkeyutl -verify -in data.sha384 -sigfile data.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_imported.der -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha384" " Verify signature with OpenSSL" test "pkcs11-tool --module $MODULE --sign --pin 0001password --id 2 -m SHA512-RSA-PKCS-PSS -i data.txt -o data.sig" " Sign with imported key and SHA512-RSA-PKCS-PSS" test "openssl pkeyutl -verify -in data.sha512 -sigfile data.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_imported.der -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha512" " Verify signature with OpenSSL" # Decrypt with imported key and PKCS1v15 test "openssl rsautl -encrypt -inkey pubkey_imported.der -pubin -in data.txt -out data.enc" " Encryp with OpenSSL using PKCS1v15" test "pkcs11-tool --module $MODULE --decrypt --pin 0001password --id 2 -m RSA-PKCS --input-file data.enc --output-file data.dec" " Decrypt using imported key" test "cmp data.dec data.txt" " Compare decrypted data with plain text data" test "rm data.enc data.dec" " Delete test data" # Decrypt with imported key and OAEP test "openssl pkeyutl -encrypt -pubin -inkey pubkey_imported.der -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha1 -pkeyopt rsa_mgf1_md:sha1 -in data.txt -out data.enc" " Encrypt with OpenSSL using OAEP and SHA1" test "pkcs11-tool --module $MODULE --decrypt --pin 0001password --id 2 -m RSA-PKCS-OAEP --hash-algorithm=SHA-1 --input-file data.enc --output-file data.dec" " Decrypt using imported key" test "cmp data.dec data.txt" " Compare decrypted data with plain text data" test "rm data.enc data.dec" " Delete test data" test "openssl pkeyutl -encrypt -pubin -inkey pubkey_imported.der -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256 -in data.txt -out data.enc" " Encrypt with OpenSSL using OAEP and SHA256" test "pkcs11-tool --module $MODULE --decrypt --pin 0001password --id 2 -m RSA-PKCS-OAEP --hash-algorithm=SHA256 --input-file data.enc --output-file data.dec" " Decrypt using imported key" test "cmp data.dec data.txt" " Compare decrypted data with plain text data" test "rm data.enc data.dec" " Delete test data" test "openssl pkeyutl -encrypt -pubin -inkey pubkey_imported.der -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha384 -in data.txt -out data.enc" " Encrypt with OpenSSL using OAEP and SHA384" test "pkcs11-tool --module $MODULE --decrypt --pin 0001password --id 2 -m RSA-PKCS-OAEP --hash-algorithm=SHA384 --input-file data.enc --output-file data.dec" " Decrypt using imported key" test "cmp data.dec data.txt" " Compare decrypted data with plain text data" test "rm data.enc data.dec" " Delete test data" test "openssl pkeyutl -encrypt -pubin -inkey pubkey_imported.der -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha512 -pkeyopt rsa_mgf1_md:sha512 -in data.txt -out data.enc" " Encrypt with OpenSSL using OAEP and SHA512" test "pkcs11-tool --module $MODULE --decrypt --pin 0001password --id 2 -m RSA-PKCS-OAEP --hash-algorithm=SHA512 --input-file data.enc --output-file data.dec" " Decrypt using imported key" test "cmp data.dec data.txt" " Compare decrypted data with plain text data" test "rm data.enc data.dec" " Delete test data" # Perform pkcs11-tool RSA tests pkcs11-tool --module $MODULE --login --pin 0001password --test # Delete keys test "pkcs11-tool --module $MODULE --login --pin 0001password --delete-object --id 1 --type privkey" " Delete generated key" test "pkcs11-tool --module $MODULE --login --pin 0001password --delete-object --id 2 --type privkey" " Delete generated key" done rm data.sha1 data.sha256 data.sha384 data.sha512 data.sig data.txt rm keypair.pem pubkey.der pubkey_imported.der echo "****************************************************" echo " Compress X509 Certificate" echo "****************************************************" openssl req -x509 -newkey rsa:4096 -out too_large_cert.der -outform DER -sha256 -days 3650 -nodes -subj '/C=01/ST=01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567/L=01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567/O=0123456789012345678901234567890123456789012345678901234567890123/OU=0123456789012345678901234567890123456789012345678901234567890123' > /dev/null 2>&1 test "pkcs11-tool --module $MODULE --login --pin 0001password --write-object too_large_cert.der --id 6464 --type cert" " Import large X509 certificate" test "pkcs11-tool --module $MODULE --login --pin 0001password --read-object --id 6464 --type cert --output-file too_large_cert_out.der" " Get imported certificate" test "cmp too_large_cert.der too_large_cert_out.der" " Compare read certificate with the one imported" test "pkcs11-tool --module $MODULE --login --pin 0001password --delete-object --id 6464 --type cert" " Delete certificate" set +eyubihsm-shell-2.7.1/resources/tests/bash/cmdline_test.sh0000755000175100017510000002154715133003406023022 0ustar runnerrunner#!/bin/bash if [ "$#" -eq 1 ]; then BIN=$1 # path to the yubihsm-shell command line tool - using default connector elif [ "$#" -gt 1 ]; then BIN="$1 -C $2" # path to the yubihsm-shell command line tool - using specified connector else BIN="yubihsm-shell" fi if [ -e yubihsm-shell_test_dir ]; then rm -rf yubihsm-shell_test_dir fi test () { set +e $1 > output.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat output.txt rm output.txt exit 1 else echo "$2 ... OK!" rm output.txt fi set -e } test_with_resp () { set +e $1 > resp.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat resp.txt rm resp.txt exit 1 else echo "$2 ... OK!" fi set -e } set -e test "$BIN --version" "yubihsm-shell --version" test "$BIN --help" "yubihsm-shell --help" test "$BIN -a get-device-info | grep \"Serial number:\"" "yubihsm-shell -a get-device-info" echo "********************************************************** " echo " Reset YubiHSM" echo "********************************************************** " test "$BIN -p password -a reset" sleep 3 echo "********************************************************** " echo " Blink" echo "********************************************************** " test "$BIN -p password -a blink" "-a blink" test "$BIN -p password -a blink --duration=5" "-a blink --duration=5" test "$BIN -p password -a blink-device" "blink-device" test "$BIN -p password -a blink-device --duration=5" "-a blink-device --duration=5" echo "********************************************************** " echo " Get Pseudo-random" echo "********************************************************** " test "$BIN -p password -a get-pseudo-random | wc -c | grep 513" "get-pseudo-random" # includes a new line test "$BIN -p password -a get-pseudo-random --out=random.txt" get-pseudo-random --out=random.txt length=$(cat random.txt | wc -c) if [ $length -ne 512 ]; then echo "Expected 512 but was $length characters. Without specifying byte count, 256 bytes (=512 characters) pseudo random number should have been produced." exit 1; fi rm random.txt test "$BIN -p password -a get-pseudo-random --count=10 | wc -c | grep 21" "get-pseudo-random --count=10" # includes a new line test "$BIN -p password -a get-pseudo-random --count=10 --out=random.txt" "get-pseudo-random --count=10 --out=random.txt" length=$(cat random.txt | wc -c) if [ $length -ne 20 ]; then echo "Expected 20 but was $length characters." exit 1; fi rm random.txt echo "********************************************************** " echo " Asymmetric Keys" echo "********************************************************** " ./test_edkey.sh "$BIN" if [ -z ${DOCKER_IMAGE} ] || [ ${DOCKER_IMAGE} != "centos:7" ]; then # This DOCKER_IMAGE environment variable is set in the build_and_test.yml github workflow. ./test_eckey.sh "$BIN" fi ./test_rsakey.sh "$BIN" echo "********************************************************** " echo " HMAC Keys" echo "********************************************************** " ./test_hmackey.sh "$BIN" echo "********************************************************** " echo " AEAD Keys" echo "********************************************************** " ./test_otpaeadkey.sh "$BIN" echo "********************************************************** " echo " Template" echo "********************************************************** " test "$BIN -p password -a get-pseudo-random --count=512 --out=template.txt" " Generate 512 pseudo random bytes" test_with_resp "$BIN -p password -a put-template -i 0 -l template -d 1 -A template-ssh --in template.txt" " Import template" id=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-object-info -i $id -t template" " Get object info" info=$($BIN -p password -a get-object-info -i $id -t template 2> /dev/null) test "echo $info | grep \"id: $id\"" " Object info contains correct ID" test "echo $info | grep \"type: template\"" " Object info contains correct type" test "echo $info | grep \"algorithm: template-ssh\"" " Object info contains correct algorithm" test "echo $info | grep 'label: \"template\"'" " Object info contains correct label" test "echo $info | grep \"domains: 1\"" " Object info contains correct domains" test "echo $info | grep \"origin: imported\"" " Object info contains correct origin" test "$BIN -p password -a get-template -i $id" " Get template" test "$BIN -p password -a delete-object -i $id -t template" " Delete template" rm resp.txt rm template.txt echo "********************************************************** " echo " Wrap Keys" echo "********************************************************** " ./test_wrapkey.sh "$BIN" echo "********************************************************** " echo " List Objects" echo "********************************************************** " test "$BIN -p password -a generate-asymmetric-key -i 100 -l ecKey -d 5,8,13 -c sign-ecdsa,derive-ecdh,sign-attestation-certificate -A ecp224" " Generate EC key for testing" test "$BIN -p password -a list-objects -A any -t any -i 100 | grep \"Found 1 object(s)\"" " List objects by ID" test "$BIN -p password -a list-objects -A any -t asymmetric-key | grep \"Found 1 object(s)\"" " List objects by type" test "$BIN -p password -a list-objects -A any -t any -d 5,8,13 | grep \"Found 2 object(s)\"" " List objects by domain" test "$BIN -p password -a list-objects -A any -t any -c sign-ecdsa,derive-ecdh,sign-attestation-certificate | grep \"Found 2 object(s)\"" " List objects by capabilities" test "$BIN -p password -a list-objects -A ecp224 -t any | grep \"Found 1 object(s)\"" " List objects by algorithm" test "$BIN -p password -a list-objects -A any -t any -l ecKey | grep \"Found 1 object(s)\"" " List objects by label" test "$BIN -p password -a delete-object -i 100 -t asymmetric-key" " Delete key" echo "********************************************************** " echo " Label Size" echo "********************************************************** " # Label 0 chars test "$BIN -p password -a generate-asymmetric-key -i 300 -d 5,8,13 -c sign-ecdsa -A ecp224" " Create key with no label" test "$BIN -p password -a get-object-info -i 300 -t asymmetric-key | grep 'label: \"\"'" " Object info contains empty label" #$BIN -p password -a list-objects -A any -t any -l "" | grep "Found 1 object(s)" # Label 39 chars test "$BIN -p password -a generate-asymmetric-key -i 200 -l abcdefghijklmnopqrstuvwxyz0123456789abc -d 5,8,13 -c sign-ecdsa -A ecp224" " Create object with 39 characters label" test "$BIN -p password -a get-object-info -i 200 -t asymmetric-key | grep 'label: \"abcdefghijklmnopqrstuvwxyz0123456789abc\"'" " Object info contains correct lable with 39 characters" test "$BIN -p password -a list-objects -A any -t any -l abcdefghijklmnopqrstuvwxyz0123456789abc | grep \"Found 1 object(s)\"" " list-objects found object with 39 characters" # Label 40 chars test "$BIN -p password -a generate-asymmetric-key -i 100 -l abcdefghijklmnopqrstuvwxyz0123456789abcd -d 5,8,13 -c sign-ecdsa -A ecp224" " Create object with 40 characters label" test "$BIN -p password -a get-object-info -i 100 -t asymmetric-key | grep 'label: \"abcdefghijklmnopqrstuvwxyz0123456789abcd\"'" " Object info contains correct lable with 40 characters" test "$BIN -p password -a list-objects -A any -t any -l abcdefghijklmnopqrstuvwxyz0123456789abcd | grep \"Found 1 object(s)\"" " list-objects found object with 40 characters" # Label 41 chars (set +e; $BIN -p password -a generate-asymmetric-key -i 400 -l "abcdefghijklmnopqrstuvwxyz0123456789abcde" -d "5,8,13" -c "sign-ecdsa" -A "ecp224"; true) 2>&1 >/dev/null | grep "Failed to generate asymmetric key: Invalid argument to a function" # Label doesn't exist test "$BIN -p password -a list-objects -A any -t any -l doesnotexist | grep \"Found 0 object(s)\"" " List objects by label that does not exist" test "$BIN -p password -a delete-object -i 100 -t asymmetric-key" " Clean up" test "$BIN -p password -a delete-object -i 200 -t asymmetric-key" " Clean up" test "$BIN -p password -a delete-object -i 300 -t asymmetric-key" " Clean up" echo "********************************************************** " echo " Authentication Keys" echo "********************************************************** " test_with_resp "$BIN -p password -a put-authentication-key -i 0 -l authkey -d 1,2,3 -c all --delegated all --new-password foo123" " Create new authentication key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN --authkey $keyid -p foo123 -a get-object-info -i 1 -t authentication-key" " Login using new authetication key" test "$BIN -p password -a delete-object -i $keyid -t authentication-key" " Delete new authentication key" cd .. rm -rf yubihsm-shell_test_dir set +e yubihsm-shell-2.7.1/resources/tests/bash/test_wrapkey.sh0000755000175100017510000005677215133003406023101 0ustar runnerrunner#!/bin/bash set -u if [ "$#" -ne 1 ]; then BIN="yubihsm-shell" else BIN=$1 # path to the yubico-piv-tool command line tool fi if [ -e yubihsm-shell_test_dir ]; then rm -rf yubihsm-shell_test_dir fi mkdir yubihsm-shell_test_dir; cd yubihsm-shell_test_dir echo test signing data > data.txt test () { set +e $1 > output.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat output.txt rm output.txt exit 1 else echo "$2 ... OK!" rm output.txt fi set -e } cmp_str_content () { set +e if [[ $1 == *"$2"* ]]; then echo " $3 in object info ... OK!" else echo "Wrong $3" echo $1 exit 1 fi set -e } test_with_resp () { set +e $1 > resp.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat resp.txt rm resp.txt exit 1 else echo "$2 ... OK!" fi set -e } set -e test "$BIN -p password -a reset" " Reset device" sleep 3 eckey=100 aeskey=200 test "$BIN -p password -a generate-asymmetric-key -i $eckey -l eckey -d 1 -c exportable-under-wrap,sign-ecdsa -A ecp224" " Generate EC Key to wrap" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) cmp_str_content "$info" "sequence: 0" "Sequence" cmp_str_content "$info" "origin: generated" "Origin" echo "**********************************" echo " aes128-ccm-wrap" echo "**********************************" echo "=== Generate key" test_with_resp "$BIN -p password -a generate-wrap-key -i 0 -l wrapkey -d 1 -c export-wrapped,import-wrapped --delegated sign-ecdsa,exportable-under-wrap -A aes128-ccm-wrap" " Generate wrap key" keyid=$(tail -1 resp.txt | awk '{print $4}') info=$($BIN -p password -a get-object-info -i $keyid -t wrap-key 2> /dev/null) cmp_str_content "$info" "algorithm: aes128-ccm-wrap" "Algorithm" cmp_str_content "$info" "length: 24" "Length" echo "=== Import key" test_with_resp "$BIN -p password -a get-pseudo-random --count 16" " Get random 16 bytes" wrapkey=$(tail -1 resp.txt | awk '{print $0}') test_with_resp "$BIN -p password -a put-wrap-key -i 0 -l imported_wrapkey -d 1 -c export-wrapped,import-wrapped --delegated sign-ecdsa,exportable-under-wrap --in=$wrapkey" " Import wrap key" import_keyid=$(tail -1 resp.txt | awk '{print $4}') info=$($BIN -p password -a get-object-info -i $import_keyid -t wrap-key 2> /dev/null) cmp_str_content "$info" "algorithm: aes128-ccm-wrap" "Algorithm" cmp_str_content "$info" "length: 24" "Length" cmp_str_content "$info" "origin: imported" "Origin" echo "=== Wrap and unwrap objects with generated wrap key" test "$BIN -p password -a get-wrapped --wrap-id $keyid -i 100 -t asymmetric-key --out key.gen_wrapped" " Wrap EC key" test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" test "$BIN -p password -a put-wrapped --wrap-id $keyid --in key.gen_wrapped" " Wrap EC key" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) cmp_str_content "$info" "sequence: 1" "Sequence" cmp_str_content "$info" "origin: generated:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: exportable-under-wrap:sign-ecdsa" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped key" echo "=== Wrap and unwrap objects with imported wrap key" test "$BIN -p password -a get-wrapped --wrap-id $import_keyid -i 100 -t asymmetric-key --out key.imp_wrapped" " Wrap EC key" test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" test "$BIN -p password -a put-wrapped --wrap-id $import_keyid --in key.imp_wrapped" " Wrap EC key" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) cmp_str_content "$info" "sequence: 2" "Sequence" cmp_str_content "$info" "origin: generated:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: exportable-under-wrap:sign-ecdsa" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped key" echo "=== Clean up" test "$BIN -p password -a delete-object -i $keyid -t wrap-key" " Delete generated wrap key" test "$BIN -p password -a delete-object -i $import_keyid -t wrap-key" " Delete imported wrap key" rm key.gen_wrapped rm key.imp_wrapped echo "**********************************" echo " aes192-ccm-wrap" echo "**********************************" echo "=== Generate key" test_with_resp "$BIN -p password -a generate-wrap-key -i 0 -l wrapkey -d 1 -c export-wrapped,import-wrapped --delegated sign-ecdsa,exportable-under-wrap -A aes192-ccm-wrap" " Generate wrap key" keyid=$(tail -1 resp.txt | awk '{print $4}') info=$($BIN -p password -a get-object-info -i $keyid -t wrap-key 2> /dev/null) cmp_str_content "$info" "algorithm: aes192-ccm-wrap" "Algorithm" cmp_str_content "$info" "length: 32" "Length" echo "=== Import key" test_with_resp "$BIN -p password -a get-pseudo-random --count 24" " Get random 16 bytes" wrapkey=$(tail -1 resp.txt | awk '{print $0}') test_with_resp "$BIN -p password -a put-wrap-key -i 0 -l imported_wrapkey -d 1 -c export-wrapped,import-wrapped --delegated sign-ecdsa,exportable-under-wrap --in=$wrapkey" " Import wrap key" import_keyid=$(tail -1 resp.txt | awk '{print $4}') info=$($BIN -p password -a get-object-info -i $import_keyid -t wrap-key 2> /dev/null) cmp_str_content "$info" "algorithm: aes192-ccm-wrap" "Algorithm" cmp_str_content "$info" "length: 32" "Length" cmp_str_content "$info" "origin: imported" "Origin" echo "=== Wrap and unwrap objects with generated wrap key" test "$BIN -p password -a get-wrapped --wrap-id $keyid -i 100 -t asymmetric-key --out key.gen_wrapped" " Wrap EC key" test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" test "$BIN -p password -a put-wrapped --wrap-id $keyid --in key.gen_wrapped" " Wrap EC key" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) cmp_str_content "$info" "sequence: 3" "Sequence" cmp_str_content "$info" "origin: generated:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: exportable-under-wrap:sign-ecdsa" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped key" echo "=== Wrap and unwrap objects with imported wrap key" test "$BIN -p password -a get-wrapped --wrap-id $import_keyid -i 100 -t asymmetric-key --out key.imp_wrapped" " Wrap EC key" test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" test "$BIN -p password -a put-wrapped --wrap-id $import_keyid --in key.imp_wrapped" " Wrap EC key" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) cmp_str_content "$info" "sequence: 4" "Sequence" cmp_str_content "$info" "origin: generated:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: exportable-under-wrap:sign-ecdsa" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped key" echo "=== Clean up" test "$BIN -p password -a delete-object -i $keyid -t wrap-key" " Delete generated wrap key" test "$BIN -p password -a delete-object -i $import_keyid -t wrap-key" " Delete imported wrap key" rm key.gen_wrapped rm key.imp_wrapped echo "**********************************" echo " aes256-ccm-wrap" echo "**********************************" echo "=== Generate key" test_with_resp "$BIN -p password -a generate-wrap-key -i 0 -l wrapkey -d 1 -c export-wrapped,import-wrapped --delegated sign-ecdsa,exportable-under-wrap -A aes256-ccm-wrap" " Generate wrap key" keyid=$(tail -1 resp.txt | awk '{print $4}') info=$($BIN -p password -a get-object-info -i $keyid -t wrap-key 2> /dev/null) cmp_str_content "$info" "algorithm: aes256-ccm-wrap" "Algorithm" cmp_str_content "$info" "length: 40" "Length" echo "=== Import key" test_with_resp "$BIN -p password -a get-pseudo-random --count 32" " Get random 16 bytes" wrapkey=$(tail -1 resp.txt | awk '{print $0}') test_with_resp "$BIN -p password -a put-wrap-key -i 0 -l imported_wrapkey -d 1 -c export-wrapped,import-wrapped --delegated sign-ecdsa,exportable-under-wrap --in=$wrapkey" " Import wrap key" import_keyid=$(tail -1 resp.txt | awk '{print $4}') info=$($BIN -p password -a get-object-info -i $import_keyid -t wrap-key 2> /dev/null) cmp_str_content "$info" "algorithm: aes256-ccm-wrap" "Algorithm" cmp_str_content "$info" "length: 40" "Length" cmp_str_content "$info" "origin: imported" "Origin" echo "=== Wrap and unwrap objects with generated wrap key" test "$BIN -p password -a get-wrapped --wrap-id $keyid -i 100 -t asymmetric-key --out key.gen_wrapped" " Wrap EC key" test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" test "$BIN -p password -a put-wrapped --wrap-id $keyid --in key.gen_wrapped" " Wrap EC key" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) cmp_str_content "$info" "sequence: 5" "Sequence" cmp_str_content "$info" "origin: generated:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: exportable-under-wrap:sign-ecdsa" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped key" echo "=== Wrap and unwrap objects with imported wrap key" test "$BIN -p password -a get-wrapped --wrap-id $import_keyid -i 100 -t asymmetric-key --out key.imp_wrapped" " Wrap EC key" test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" test "$BIN -p password -a put-wrapped --wrap-id $import_keyid --in key.imp_wrapped" " Wrap EC key" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) cmp_str_content "$info" "sequence: 6" "Sequence" cmp_str_content "$info" "origin: generated:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: exportable-under-wrap:sign-ecdsa" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped key" echo "=== Clean up" test "$BIN -p password -a delete-object -i $keyid -t wrap-key" " Delete generated wrap key" test "$BIN -p password -a delete-object -i $import_keyid -t wrap-key" " Delete imported wrap key" rm key.gen_wrapped rm key.imp_wrapped device_info=$($BIN -p password -a get-device-info 2> /dev/null) if [[ "$device_info" != *"aes-kwp"* ]]; then test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" exit 0 fi aes_enabled=false if [[ "$device_info" == *"aes-cbc"* ]]; then aes_enabled=true test "$BIN -p password -a generate-symmetric-key -i $aeskey -l aeskey -d 1 -c exportable-under-wrap,encrypt-cbc,decrypt-cbc -A aes128" " Generate AES Key to wrap" test_with_resp "$BIN -p password -a get-pseudo-random --count 16" " Get random 16 bytes for IV" iv=$(tail -1 resp.txt | awk '{print $0}') test_with_resp "$BIN -p password -a get-pseudo-random --count 32" " Get random 32 bytes to test encryption" data=$(tail -1 resp.txt | awk '{print $0}') fi RSA_KEYSIZE=("2048" "3072" "4096") seq_ec=6 seq_aes=0 for k in ${RSA_KEYSIZE[@]}; do echo "**********************************" echo " RSA$k" echo "**********************************" echo "=== Generate RSA wrap keys" test_with_resp "$BIN -p password -a generate-wrap-key -i 0 -l wrapkey -c import-wrapped --delegated exportable-under-wrap,sign-ecdsa,encrypt-cbc,decrypt-cbc -A rsa$k" " Generate RSA wrap key" keyid=$(tail -1 resp.txt | awk '{print $4}') info=$($BIN -p password -a get-object-info -i $keyid -t wrap-key 2> /dev/null) cmp_str_content "$info" "algorithm: rsa$k" "Algorithm" cmp_str_content "$info" "origin: generated" "Origin" test "$BIN -p password -a get-public-key -i $keyid -t wrap-key --out public_wrapkey.pem" " Export rsa public wrap key" test "$BIN -p password -a put-public-wrapkey -i $keyid -c export-wrapped --delegated exportable-under-wrap,sign-ecdsa,encrypt-cbc,decrypt-cbc --in public_wrapkey.pem" " Import RSA public wrap key" rm public_wrapkey.pem echo "=== Wrap and unwrap EC object with generated RSA wrap key" test "$BIN -p password -a get-rsa-wrapped --wrap-id $keyid -i $eckey -t asymmetric-key --out rsawrapped.object" " Export wrapped EC object" test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" test "$BIN -p password -a put-rsa-wrapped --wrap-id $keyid --in rsawrapped.object" " Import wrapped EC object" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) seq_ec=$((seq_ec+1)) cmp_str_content "$info" "sequence: $seq_ec" "Sequence" cmp_str_content "$info" "capabilities: exportable-under-wrap:sign-ecdsa" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped EC key" rm rsawrapped.object echo "=== Wrap and unwrap EC key material with generated RSA wrap key" test "$BIN -p password -a get-rsa-wrapped-key --wrap-id $keyid -i $eckey -t asymmetric-key --oaep rsa-oaep-sha1 --mgf1 mgf1-sha384 --out rsawrapped.key" " Export wrapped EC key material" test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" test "$BIN -p password -a put-rsa-wrapped-key --wrap-id $keyid -i $eckey -t asymmetric-key -A ecp224 -c exportable-under-wrap,sign-ecdsa --oaep rsa-oaep-sha1 --mgf1 mgf1-sha384 --in rsawrapped.key" " Import wrapped EC key material" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) seq_ec=$((seq_ec+1)) cmp_str_content "$info" "sequence: $seq_ec" "Sequence" cmp_str_content "$info" "origin: imported:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: exportable-under-wrap:sign-ecdsa" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped EC key" rm rsawrapped.key if [[ "$aes_enabled" = true ]]; then echo "=== Wrap and unwrap AES object with generated RSA wrap key" test "$BIN -p password -a get-rsa-wrapped --wrap-id $keyid -i $aeskey -t symmetric-key --out rsawrapped.object" " Export wrapped AES object" test "$BIN -p password -a delete-object -i $aeskey -t symmetric-key" " Delete AES key" test "$BIN -p password -a put-rsa-wrapped --wrap-id $keyid --in rsawrapped.object" " Import wrapped AES object" info=$($BIN -p password -a get-object-info -i $aeskey -t symmetric-key 2> /dev/null) seq_aes=$((seq_aes+1)) cmp_str_content "$info" "sequence: $seq_aes" "Sequence" cmp_str_content "$info" "capabilities: decrypt-cbc:encrypt-cbc:exportable-under-wrap" "Capabilities" test "$BIN -p password -a encrypt-aescbc -i $aeskey --iv $iv --in $data --out data.enc" " Perform encryption with imported wrapped AES key" test_with_resp "$BIN -p password -a decrypt-aescbc -i $aeskey --iv $iv --in data.enc" " Perform decryption with imported wrapped AES key" data_dec=$(tail -1 resp.txt | awk '{print $0}') if [[ "$data" == "$data_dec" ]]; then echo " Compare decrypted data to plain text ... OK!" else $BIN -p password -a decrypt-aescbc -i $aeskey --iv $iv --in data.enc --out data.dec exit fi rm rsawrapped.object rm data.enc echo "=== Wrap and unwrap AES key material with generated RSA wrap key" test "$BIN -p password -a get-rsa-wrapped-key --wrap-id $keyid -i $aeskey -t symmetric-key --oaep rsa-oaep-sha384 --mgf1 mgf1-sha1 --out rsawrapped.key" " Export wrapped AES key material" test "$BIN -p password -a delete-object -i $aeskey -t symmetric-key" " Delete AES key" test "$BIN -p password -a put-rsa-wrapped-key --wrap-id $keyid -i $aeskey -t symmetric-key -A aes128 -c exportable-under-wrap,decrypt-cbc,encrypt-cbc --oaep rsa-oaep-sha384 --mgf1 mgf1-sha1 --in rsawrapped.key" " Import wrapped AES key material" info=$($BIN -p password -a get-object-info -i $aeskey -t symmetric-key 2> /dev/null) seq_aes=$((seq_aes+1)) cmp_str_content "$info" "sequence: $seq_aes" "Sequence" cmp_str_content "$info" "origin: imported:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: decrypt-cbc:encrypt-cbc:exportable-under-wrap" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped EC key" test "$BIN -p password -a encrypt-aescbc -i $aeskey --iv $iv --in $data --out data.enc" " Perform encryption with imported wrapped AES key" test_with_resp "$BIN -p password -a decrypt-aescbc -i $aeskey --iv $iv --in data.enc" " Perform decryption with imported wrapped AES key" data_dec=$(tail -1 resp.txt | awk '{print $0}') if [[ "$data" == "$data_dec" ]]; then echo " Compare decrypted data to plain text ... OK!" else $BIN -p password -a decrypt-aescbc -i $aeskey --iv $iv --in data.enc --out data.dec exit fi rm rsawrapped.key rm data.enc fi echo "=== Import RSA wrap keys" test "openssl genrsa -out keypair.pem $k" " Generate RSA key with OpenSSL" test "openssl rsa -in keypair.pem -pubout -out key.pub" " Extract public key from OpenSSL generated keypair" test_with_resp "$BIN -p password -a put-rsa-wrapkey -i 0 -d 1 -c import-wrapped --delegated exportable-under-wrap,sign-ecdsa,encrypt-cbc,decrypt-cbc --in keypair.pem" " Import RSA wrap key" import_keyid=$(tail -1 resp.txt | awk '{print $4}') info=$($BIN -p password -a get-object-info -i $import_keyid -t wrap-key 2> /dev/null) cmp_str_content "$info" "algorithm: rsa$k" "Algorithm" cmp_str_content "$info" "origin: imported" "Origin" test "$BIN -p password -a put-public-wrapkey -i $import_keyid -c export-wrapped --delegated exportable-under-wrap,sign-ecdsa,encrypt-cbc,decrypt-cbc --in key.pub" " Import RSA public wrap key" rm keypair.pem rm key.pub echo "=== Wrap and unwrap EC object with imported RSA wrap key" test "$BIN -p password -a get-rsa-wrapped --wrap-id $import_keyid -i $eckey -t asymmetric-key --out rsawrapped.object" " Export wrapped EC object" test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" test "$BIN -p password -a put-rsa-wrapped --wrap-id $import_keyid --in rsawrapped.object" " Import wrapped EC object" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) seq_ec=$((seq_ec+1)) cmp_str_content "$info" "sequence: $seq_ec" "Sequence" cmp_str_content "$info" "origin: imported:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: exportable-under-wrap:sign-ecdsa" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped EC key" rm rsawrapped.object echo "=== Wrap and unwrap EC key material with imported RSA wrap key" test "$BIN -p password -a get-rsa-wrapped-key --wrap-id $import_keyid -i $eckey -t asymmetric-key --oaep rsa-oaep-sha512 --mgf1 mgf1-sha512 --out rsawrapped.key" " Export wrapped EC key material" test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" test "$BIN -p password -a put-rsa-wrapped-key --wrap-id $import_keyid -i $eckey -t asymmetric-key -A ecp224 -c exportable-under-wrap,sign-ecdsa --oaep rsa-oaep-sha512 --mgf1 mgf1-sha512 --in rsawrapped.key" " Import wrapped EC key material" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) seq_ec=$((seq_ec+1)) cmp_str_content "$info" "sequence: $seq_ec" "Sequence" cmp_str_content "$info" "origin: imported:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: exportable-under-wrap:sign-ecdsa" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped EC key" rm rsawrapped.key if [[ "$aes_enabled" = true ]]; then echo "=== Wrap and unwrap AES object with imported RSA wrap key" test "$BIN -p password -a get-rsa-wrapped --wrap-id $import_keyid -i $aeskey -t symmetric-key --out rsawrapped.object" " Export wrapped AES object" test "$BIN -p password -a delete-object -i $aeskey -t symmetric-key" " Delete AES key" test "$BIN -p password -a put-rsa-wrapped --wrap-id $import_keyid --in rsawrapped.object" " Import wrapped AES object" info=$($BIN -p password -a get-object-info -i $aeskey -t symmetric-key 2> /dev/null) seq_aes=$((seq_aes+1)) cmp_str_content "$info" "sequence: $seq_aes" "Sequence" cmp_str_content "$info" "origin: imported:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: decrypt-cbc:encrypt-cbc:exportable-under-wrap" "Capabilities" test "$BIN -p password -a encrypt-aescbc -i $aeskey --iv $iv --in $data --out data.enc" " Perform encryption with imported wrapped AES key" test_with_resp "$BIN -p password -a decrypt-aescbc -i $aeskey --iv $iv --in data.enc" " Perform decryption with imported wrapped AES key" data_dec=$(tail -1 resp.txt | awk '{print $0}') if [[ "$data" == "$data_dec" ]]; then echo " Compare decrypted data to plain text ... OK!" else $BIN -p password -a decrypt-aescbc -i $aeskey --iv $iv --in data.enc --out data.dec exit fi rm rsawrapped.object rm data.enc echo "=== Wrap and unwrap AES key material with imported RSA wrap key" test "$BIN -p password -a get-rsa-wrapped-key --wrap-id $import_keyid -i $aeskey -t symmetric-key --oaep rsa-oaep-sha1 --mgf1 mgf1-sha384 --out rsawrapped.key" " Export wrapped AES key material" test "$BIN -p password -a delete-object -i $aeskey -t symmetric-key" " Delete AES key" test "$BIN -p password -a put-rsa-wrapped-key --wrap-id $import_keyid -i $aeskey -t symmetric-key -A aes128 -c exportable-under-wrap,decrypt-cbc,encrypt-cbc --oaep rsa-oaep-sha1 --mgf1 mgf1-sha384 --in rsawrapped.key" " Import wrapped AES key material" info=$($BIN -p password -a get-object-info -i $aeskey -t symmetric-key 2> /dev/null) seq_aes=$((seq_aes+1)) cmp_str_content "$info" "sequence: $seq_aes" "Sequence" cmp_str_content "$info" "origin: imported:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: decrypt-cbc:encrypt-cbc:exportable-under-wrap" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped EC key" test "$BIN -p password -a encrypt-aescbc -i $aeskey --iv $iv --in $data --out data.enc" " Perform encryption with imported wrapped AES key" test_with_resp "$BIN -p password -a decrypt-aescbc -i $aeskey --iv $iv --in data.enc" " Perform decryption with imported wrapped AES key" data_dec=$(tail -1 resp.txt | awk '{print $0}') if [[ "$data" == "$data_dec" ]]; then echo " Compare decrypted data to plain text ... OK!" else $BIN -p password -a decrypt-aescbc -i $aeskey --iv $iv --in data.enc --out data.dec exit fi rm rsawrapped.key rm data.enc fi echo "=== Clean up" test "$BIN -p password -a delete-object -i $keyid -t wrap-key" " Delete generated RSA wrap key" test "$BIN -p password -a delete-object -i $keyid -t public-wrap-key" " Delete generated RSA public wrap key" test "$BIN -p password -a delete-object -i $import_keyid -t wrap-key" " Delete imported RSA wrap key" test "$BIN -p password -a delete-object -i $import_keyid -t public-wrap-key" " Delete imported RSA public wrap key" done #test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" #if [[ "$aes_enabled" = true ]]; then # test "$BIN -p password -a delete-object -i $aeskey -t symmetric-key" " Delete AES key" #fi test "$BIN -p password -a reset" " Reset device" cd .. rm -rf yubihsm-shell_test_dir set +e yubihsm-shell-2.7.1/resources/tests/bash/test_hmackey.sh0000755000175100017510000000720415133003406023022 0ustar runnerrunner#!/bin/bash set -u if [ "$#" -ne 1 ]; then BIN="yubihsm-shell" else BIN=$1 # path to the yubico-piv-tool command line tool fi if [ -e yubihsm-shell_test_dir ]; then rm -rf yubihsm-shell_test_dir fi mkdir yubihsm-shell_test_dir; cd yubihsm-shell_test_dir echo test signing data > data.txt test () { set +e $1 > output.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat output.txt rm output.txt exit 1 else echo "$2 ... OK!" rm output.txt fi set -e } test_with_resp () { set +e $1 > resp.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat resp.txt rm resp.txt exit 1 else echo "$2 ... OK!" fi set -e } set -e echo "====================== HMAC keys ===================== " echo "------------- hmac-sha1" test_with_resp "$BIN -p password -a generate-hmac-key -i 0 -l hmackey -d 1,2,3 -c sign-hmac -A hmac-sha1" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-object-info -i $keyid -t hmac-key" " Get object info" info=$($BIN -p password -a get-object-info -i $keyid -t hmac-key 2> /dev/null) test "echo $info | grep \"id: $keyid\"" " Object info contains correct ID" test "echo $info | grep \"type: hmac-key\"" " Object info contains correct type" test "echo $info | grep \"algorithm: hmac-sha1\"" " Object info contains correct algorithm" test "echo $info | grep 'label: \"hmackey\"'" " Object info contains correct label" test "echo $info | grep \"domains: 1:2:3\"" " Object info contains correct domains" test "echo $info | grep \"origin: generated\"" " Object info contains correct origin" test "echo $info | grep \"capabilities: sign-hmac\"" " Object info contains correct capabilities" #$BIN -p password -a sign-hmac -i $keyid --in data.txt test "$BIN -p password -a delete-object -i $keyid -t hmac-key" " Delete key" echo "------------- hmac-sha256" test_with_resp "$BIN -p password -a generate-hmac-key -i 0 -l hmackey -d 1,2,3 -c sign-hmac -A hmac-sha256" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-object-info -i $keyid -t hmac-key" " Get object info" info=$($BIN -p password -a get-object-info -i $keyid -t hmac-key 2> /dev/null) test "echo $info | grep \"algorithm: hmac-sha256\"" " Object info contains correct algorithm" #$BIN -p password -a sign-hmac -i $keyid --in data.txt test "$BIN -p password -a delete-object -i $keyid -t hmac-key" " Delete key" echo "------------- hmac-sha384" test_with_resp "$BIN -p password -a generate-hmac-key -i 0 -l hmackey -d 1,2,3 -c sign-hmac -A hmac-sha384" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-object-info -i $keyid -t hmac-key" " Get object info" info=$($BIN -p password -a get-object-info -i $keyid -t hmac-key 2> /dev/null) test "echo $info | grep \"algorithm: hmac-sha384\"" " Object info contains correct algorithm" #$BIN -p password -a sign-hmac -i $keyid --in data.txt test "$BIN -p password -a delete-object -i $keyid -t hmac-key" " Delete key" echo "------------- hmac-sha512" test_with_resp "$BIN -p password -a generate-hmac-key -i 0 -l hmackey -d 1,2,3 -c sign-hmac -A hmac-sha512" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-object-info -i $keyid -t hmac-key" " Get object info" info=$($BIN -p password -a get-object-info -i $keyid -t hmac-key 2> /dev/null) test "echo $info | grep \"algorithm: hmac-sha512\"" " Object info contains correct algorithm" #$BIN -p password -a sign-hmac -i $keyid --in data.txt test "$BIN -p password -a delete-object -i $keyid -t hmac-key" " Delete key" cd .. rm -rf yubihsm-shell_test_dir set +e yubihsm-shell-2.7.1/resources/tests/bash/test_x509template.pem0000644000175100017510000000172515133003406024010 0ustar runnerrunner-----BEGIN CERTIFICATE----- MIICpzCCAY+gAwIBAgIRALnaMgizd13cmPh34E4HNz0wDQYJKoZIhvcNAQELBQAw KjEoMCYGA1UEAwwfWXViaUhTTTIgQXR0ZXN0YXRpb24gKDEzMjAwNTAxKTAgFw0x NzAxMDEwMDAwMDBaGA8yMDcxMTAwNTAwMDAwMFowKDEmMCQGA1UEAwwdWXViaUhT TSBBdHRlc3RhdGlvbiBpZDoweDU2MGQwTjAQBgcqhkjOPQIBBgUrgQQAIQM6AATn 8QLCgsBZlpkoqdMOTbWS/tOiXfI1aOMrUQC+w6rWw8WwEbJ7LjqoPwdWg0DKrXeA 7sAEMUKX4aOBnTCBmjATBgorBgEEAYLECgQBBAUEAwIBAzAUBgorBgEEAYLECgQC BAYCBADJbHUwEgYKKwYBBAGCxAoEAwQEAwIAATATBgorBgEEAYLECgQEBAUDAwAQ kDAZBgorBgEEAYLECgQFBAsDCQAAAAAEAAAIgDASBgorBgEEAYLECgQGBAQCAlYN MBUGCisGAQQBgsQKBAkEBwwFZWNLZXkwDQYJKoZIhvcNAQELBQADggEBAEV/0jl7 ulAmLLiYGV8ELoavjtJ3wmMLyJpSURC8WPO8MucAopIsh0URXKpjLjHQHqscdAbP DyT+/l1VfFS7Fvsz/OXeMP1dYzpoYzw4iyHFkvf5G8k0hxY+BEqBa89MXKGrcDo0 iu0lSusaEJF2zq3PH3hnPIXm9SJDfWcZ7iueA0xGu6miUz3rHklnbPUqaM/omGyV MgAtLOolX7rnW7E3MEkAOII1kbwv8C/NlseKXyECRvAn2reAMH11c/t2BvGMbD81 OGTPZ2OvfNJcPnzy1olxE0Ajew5CrOB2XrOaqhVrNPA4aqpCT3ukMv60m6TXsHnU RdEhPSf0SomH7MQ= -----END CERTIFICATE----- yubihsm-shell-2.7.1/resources/tests/bash/test_otpaeadkey.sh0000755000175100017510000000646615133003406023540 0ustar runnerrunner#!/bin/bash set -u if [ "$#" -ne 1 ]; then BIN="yubihsm-shell" else BIN=$1 # path to the yubico-piv-tool command line tool fi if [ -e yubihsm-shell_test_dir ]; then rm -rf yubihsm-shell_test_dir fi mkdir yubihsm-shell_test_dir; cd yubihsm-shell_test_dir echo test signing data > data.txt test () { set +e $1 > output.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat output.txt rm output.txt exit 1 else echo "$2 ... OK!" rm output.txt fi set -e } test_with_resp () { set +e $1 > resp.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat resp.txt rm resp.txt exit 1 else echo "$2 ... OK!" fi set -e } set -e echo "====================== AEAD keys ===================== " echo "------------- AEAD Key 128" test_with_resp "$BIN -p password -a generate-otp-aead-key -i 0 -l aeadkey -d 1,2,3 -c randomize-otp-aead -A aes128-yubico-otp --nonce 0x01020304" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $5}') test "$BIN -p password -a get-object-info -i $keyid -t otp-aead-key" " Get object info" info=$($BIN -p password -a get-object-info -i $keyid -t otp-aead-key 2> /dev/null) test "echo $info | grep \"id: $keyid\"" " Object info contains correct ID" test "echo $info | grep \"type: otp-aead-key\"" " Object info contains correct type" test "echo $info | grep \"algorithm: aes128-yubico-otp\"" " Object info contains correct algorithm" test "echo $info | grep 'label: \"aeadkey\"'" " Object info contains correct label" test "echo $info | grep \"domains: 1:2:3\"" " Object info contains correct domains" test "echo $info | grep \"origin: generated\"" " Object info contains correct origin" test "echo $info | grep \"capabilities: randomize-otp-aead\"" " Object info contains correct capabilities" test "$BIN -p password -a randomize-otp-aead -i $keyid" " Randomize OTP AEAD" test "$BIN -p password -a delete-object -i $keyid -t otp-aead-key" " Delete key" echo "------------- AEAD Key 128" test_with_resp "$BIN -p password -a generate-otp-aead-key -i 0 -l aeadkey -d 1,2,3 -c randomize-otp-aead -A aes192-yubico-otp --nonce 0x01020304" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $5}') test "$BIN -p password -a get-object-info -i $keyid -t otp-aead-key" " Get object info" info=$($BIN -p password -a get-object-info -i $keyid -t otp-aead-key 2> /dev/null) test "echo $info | grep \"algorithm: aes192-yubico-otp\"" " Object info contains correct algorithm" test "$BIN -p password -a randomize-otp-aead -i $keyid" " Randomize OTP AEAD" test "$BIN -p password -a delete-object -i $keyid -t otp-aead-key" " Delete key" echo "------------- AEAD Key 256" test_with_resp "$BIN -p password -a generate-otp-aead-key -i 0 -l aeadkey -d 1,2,3 -c randomize-otp-aead -A aes256-yubico-otp --nonce 0x01020304" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $5}') test "$BIN -p password -a get-object-info -i $keyid -t otp-aead-key" " Get object info" info=$($BIN -p password -a get-object-info -i $keyid -t otp-aead-key 2> /dev/null) test "echo $info | grep \"algorithm: aes256-yubico-otp\"" " Object info contains correct algorithm" test "$BIN -p password -a randomize-otp-aead -i $keyid" " Randomize OTP AEAD" test "$BIN -p password -a delete-object -i $keyid -t otp-aead-key" " Delete key" cd .. rm -rf yubihsm-shell_test_dir set +e yubihsm-shell-2.7.1/resources/tests/bash/reg.dat0000644000175100017510000000264015133003406021251 0ustar runnerrunnerZ355tsD9teEqE1c5Viy90V1J6S9/vFJVofKeCQ2ssvwwgfT7fHp54KPc4fpZKn3Y1ZRdNBkfxFVu7e1bMpL1vCxOsIwtKGnIShx42Te7iVo9oFBzjomisnRmauAx+drsFX2T0HPdQnexo+uZ8cXQ1LfOPfI80fHfnnZ97aC3YYtomxv4ieCqQNzn17pUhP/QBUHvr3huq63+1CQ7P5iHPq4/HzmQmA8zbeYPMgRxX3r7DMF8GphgsJRU/sFJC3IL2XhYVoR/j5WgzG4ugPz2001wefAO3JOe7nryNTrnl+BbD0CcvF5u7i9bfME5pZTnkqsz7o3Wu+kXAb+LGwVyQt1KRtEAAAAcc3NoLXJzYS1jZXJ0LXYwMUBvcGVuc3NoLmNvbQAAACCboUHYTJF015XKlH4MqI+aaPJePR7MbI2teXDYvVKUhAAAAAMBAAEAAAEBAK3EX7uFmuRyX/X3eGz+Mn7EyLn/76taYJzPP4WXd0KftRV2Y0TqAK8qvQUOReMaloQzRqRgxhbnuQP/l8Zz4eXKpE8jEFvlJng+HZbvYCGW3oMOjLBjN1c0zy1zM8tjxw9LAYSXD8vtvaa77owR1Jive5PB4kNQ9zF+UCyukOAeuqcDI43W8XVIjBmxaUOIKQxy5hF6anXdXlUFf/mtD2WM+tmT60hhW1JT9T8l+49et9XywWTJpYDLoz8c6JuBq92aDfR+MKdZM46MR96JKxP1AQpSXSjWktWt3WPnFcVhHHi8D6ZO1VQA2PDOTqOWZq9FY3EFqi1PQDo/2B5QOGkAAAAAAAAAAAAAAAEAAAAPdXNlckB5dWJpY28uY29tAAAACAAAAAR1c2VyAAAAAGd+eIoAAAAAZ38GVgAAAAAAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQCtRLg8mAY0p1CiXxrdTttMMXAI0BAdLMWe4xHbgll2zOSkVWl2z/+Bbb1MNxPOzGrahp6hI8kumeTmq976LY2+6An1grKrvmGHmBP8GmlCKl43hXMsYE+lWrFVoXuZvL6XYe0w09GEdswvVmoHbpARMRY+x03xq/uUNL91J0qYdscndQVpvv0vbRCEq31yBnMXznaj1vhs99SX9SENa6HBwzt6a1ezhPo7bvLbKi5sxAOYJlkgceK0X8Do/v9IUGV0gMRrouky/88SSiKN/8+PGqDUgVFs0Ntq9YcibWVdzGgUQ6G4nKlEIyYDJIn+9NXze6mV1PJ0yJNLYAyVUWBRyubihsm-shell-2.7.1/resources/tests/bash/test_rsakey.sh0000755000175100017510000003534715133003406022710 0ustar runnerrunner#!/bin/bash set -u if [ "$#" -ne 1 ]; then BIN="yubihsm-shell" else BIN=$1 # path to the yubihsm-shell command line tool fi if [ -e yubihsm-shell_test_dir ]; then rm -rf yubihsm-shell_test_dir fi mkdir yubihsm-shell_test_dir; cd yubihsm-shell_test_dir echo test signing and decryption data > data.txt test () { set +e $1 > output.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat output.txt rm output.txt exit 1 else echo " $2 ... OK!" rm output.txt fi set -e } test_with_resp () { set +e $1 > resp.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat resp.txt rm resp.txt exit 1 else echo " $2 ... OK!" fi set -e } set -e echo "====================== RSA keys ===================== " RSA_KEYSIZE=("2048" "3072" "4096") for k in ${RSA_KEYSIZE[@]}; do echo "**********************************" echo " RSA$k" echo "**********************************" echo "=== Generate key" test_with_resp "$BIN -p password -a generate-asymmetric-key -i 0 -l rsaKey -d 1 -c sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate -A rsa$k" "Generate key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-object-info -i $keyid -t asymmetric-key" "Get object info" info=$($BIN -p password -a get-object-info -i $keyid -t asymmetric-key 2> /dev/null) test "echo $info | grep \"id: $keyid\"" "Object info contains correct ID" test "echo $info | grep \"type: asymmetric-key\"" "Object info contains correct type" test "echo $info | grep \"algorithm: rsa$k\"" "Object info contains correct algorithm" test "echo $info | grep 'label: \"rsaKey\"'" "Object info contains correct label" test "echo $info | grep \"domains: 1\"" "Object info contains correct domains" test "echo $info | grep \"origin: generated\"" "Object info contains correct origin" test "echo $info | grep \"capabilities: decrypt-oaep:decrypt-pkcs:sign-attestation-certificate:sign-pkcs:sign-pss\"" "Object info contains correct capabilities" test "$BIN -p password -a get-public-key -i $keyid --outformat=PEM --out pubkey_rsa$k.pem" "Get public key" echo "=== Import key:" test "openssl genrsa -out rsa$k-keypair.pem $k" "Generate key with OpenSSL" test_with_resp "$BIN -p password -a put-asymmetric-key -i 0 -l rsaKeyImport -d 2 -c sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate --in=rsa$k-keypair.pem" "Import key" import_keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-object-info -i $import_keyid -t asymmetric-key" "Get object info" info=$($BIN -p password -a get-object-info -i $import_keyid -t asymmetric-key 2> /dev/null) test "echo $info | grep \"id: $import_keyid\"" "Object info contains correct ID" test "echo $info | grep \"type: asymmetric-key\"" "Object info contains correct type" test "echo $info | grep \"algorithm: rsa$k\"" "Object info contains correct algorithm" test "echo $info | grep 'label: \"rsaKeyImport\"'" "Object info contains correct label" test "echo $info | grep \"domains: 2\"" "Object info contains correct domains" test "echo $info | grep \"origin: imported\"" "Object info contains correct origin" test "echo $info | grep \"capabilities: decrypt-oaep:decrypt-pkcs:sign-attestation-certificate:sign-pkcs:sign-pss\"" "Object info contains correct capabilities" test "$BIN -p password -a get-public-key -i $import_keyid --outformat=PEM --out pubkey_rsa$k.imported.pem" "Get public key" echo "=== Signing with generated key:" test "$BIN -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha1 --in data.txt --outformat binary --out data.$k-pkcs1sha1gen.sig" "Sign with rsa-pkcs1-sha1" test "openssl dgst -sha1 -verify pubkey_rsa$k.pem -signature data.$k-pkcs1sha1gen.sig data.txt" "Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha256 --in data.txt --outformat binary --out data.$k-pkcs1sha256gen.sig" "Sign with rsa-pkcs1-sha256" test "openssl dgst -sha256 -verify pubkey_rsa$k.pem -signature data.$k-pkcs1sha256gen.sig data.txt" "Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha384 --in data.txt --outformat binary --out data.$k-pkcs1sha384gen.sig" "Sign with rsa-pkcs1-sha384" test "openssl dgst -sha384 -verify pubkey_rsa$k.pem -signature data.$k-pkcs1sha384gen.sig data.txt" "Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha512 --in data.txt --outformat binary --out data.$k-pkcs1sha512gen.sig" "Sign with rsa-pkcs1-sha512" test "openssl dgst -sha512 -verify pubkey_rsa$k.pem -signature data.$k-pkcs1sha512gen.sig data.txt" "Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $keyid -A rsa-pss-sha1 --in data.txt --outformat binary --out data.$k-psssha1gen.sig" "Sign with rsa-pss-sha1" test "openssl dgst -sha1 -binary -out data.sha1 data.txt" "Hash data with OpenSSL" test "openssl pkeyutl -verify -in data.sha1 -sigfile data.$k-psssha1gen.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_rsa$k.pem -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha1" "Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $keyid -A rsa-pss-sha256 --in data.txt --outformat binary --out data.$k-psssha256gen.sig" "Sign with rsa-pss-sha256" test "openssl dgst -sha256 -binary -out data.sha256 data.txt" "Hash data with OpenSSL" test "openssl pkeyutl -verify -in data.sha256 -sigfile data.$k-psssha256gen.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_rsa$k.pem -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha256" "Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $keyid -A rsa-pss-sha384 --in data.txt --outformat binary --out data.$k-psssha384gen.sig" "Sign with rsa-pss-sha384" test "openssl dgst -sha384 -binary -out data.sha384 data.txt" "Hash data with OpenSSL" test "openssl pkeyutl -verify -in data.sha384 -sigfile data.$k-psssha384gen.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_rsa$k.pem -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha384" "Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $keyid -A rsa-pss-sha512 --in data.txt --outformat binary --out data.$k-psssha512gen.sig" "Sign with rsa-pss-sha512" test "openssl dgst -sha512 -binary -out data.sha512 data.txt" "Hash data with OpenSSL" test "openssl pkeyutl -verify -in data.sha512 -sigfile data.$k-psssha512gen.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_rsa$k.pem -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha512" "Verify signature with OpenSSL" echo "=== Signing with imported key:" test "$BIN -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha1 --in data.txt --outformat binary --out data.$k-pkcs1sha1import.sig" "Sign with rsa-pkcs1-sha1" test "openssl dgst -sha1 -verify pubkey_rsa$k.imported.pem -signature data.$k-pkcs1sha1import.sig data.txt" "Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha256 --in data.txt --outformat binary --out data.$k-pkcs1sha256import.sig" "Sign with rsa-pkcs1-sha256" test "openssl dgst -sha256 -verify pubkey_rsa$k.imported.pem -signature data.$k-pkcs1sha256import.sig data.txt" "Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha384 --in data.txt --outformat binary --out data.$k-pkcs1sha384import.sig" "Sign with rsa-pkcs1-sha384" test "openssl dgst -sha384 -verify pubkey_rsa$k.imported.pem -signature data.$k-pkcs1sha384import.sig data.txt" "Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha512 --in data.txt --outformat binary --out data.$k-pkcs1sha512import.sig" "Sign with rsa-pkcs1-sha512" test "openssl dgst -sha512 -verify pubkey_rsa$k.imported.pem -signature data.$k-pkcs1sha512import.sig data.txt" "Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $import_keyid -A rsa-pss-sha1 --in data.txt --outformat binary --out data.$k-psssha1import.sig" "Sign with rsa-pss-sha1" test "openssl dgst -sha1 -binary -out data.sha1 data.txt" "Hash data with OpenSSL" test "openssl pkeyutl -verify -in data.sha1 -sigfile data.$k-psssha1import.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_rsa$k.imported.pem -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha1" "Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $import_keyid -A rsa-pss-sha256 --in data.txt --outformat binary --out data.$k-psssha256import.sig" "Sign with rsa-pss-sha256" test "openssl dgst -sha256 -binary -out data.sha256 data.txt" "Hash data with OpenSSL" test "openssl pkeyutl -verify -in data.sha256 -sigfile data.$k-psssha256import.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_rsa$k.imported.pem -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha256" "Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $import_keyid -A rsa-pss-sha384 --in data.txt --outformat binary --out data.$k-psssha384import.sig" "Sign with rsa-pss-sha384" test "openssl dgst -sha384 -binary -out data.sha384 data.txt" "Hash data with OpenSSL" test "openssl pkeyutl -verify -in data.sha384 -sigfile data.$k-psssha384import.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_rsa$k.imported.pem -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha384" "Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $import_keyid -A rsa-pss-sha512 --in data.txt --outformat binary --out data.$k-psssha512import.sig" "Sign with rsa-pss-sha512" test "openssl dgst -sha512 -binary -out data.sha512 data.txt" "Hash data with OpenSSL" test "openssl pkeyutl -verify -in data.sha512 -sigfile data.$k-psssha512import.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_rsa$k.imported.pem -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha512" "Verify signature with OpenSSL" echo "=== Make self signed certificate:" set +e $BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 2>&1 > /dev/null # Some YubiHSMs does not have default attestation certificate def_attestation=$? set -e if [ $def_attestation -eq 0 ]; then test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem" "Sign attestation cert with default key" test "openssl x509 -in cert.pem -out cert.der -outform DER" "Convert cert format" test "$BIN -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der" "Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der" "Import attestation cert as template cert (same ID as imported key)" test "rm cert.der" "Cleaning up" else test "$BIN -p password -a put-opaque -i $keyid -l template_cert_gen -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" "Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert_imp -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" "Import attestation cert as template cert (same ID as imported key)" fi test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem" "Sign attestation with same key (aka. get selfsigned cert)" test "$BIN -p password -a delete-object -i $keyid -t opaque" "Delete template cert" test "$BIN -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --informat=PEM --in selfsigned_cert.pem" "Import selfsigned cert with same key ID" test "rm selfsigned_cert.pem" "Cleaning up" #-- Sign attestation certificate test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.pem" "Sign attestation cert with imported key" test "rm selfsigned_cert.pem" "Cleaning up" test "$BIN -p password -a delete-object -i $import_keyid -t opaque" "Delete certificate template" test "$BIN -p password -a delete-object -i $keyid -t opaque" "Delete certificate" echo "=== Decrypt with generated key and PKCS1v15:" test "openssl rsautl -encrypt -inkey pubkey_rsa$k.pem -pubin -in data.txt -out data.enc" "Encryp with OpenSSL" test "$BIN -p password -a decrypt-pkcs1v15 -i $keyid --in data.enc --out data.dec" "Decrypt with yubihsm-shell" test "cmp data.txt data.dec" "Compare decrypted data with plain text data" test "rm data.dec" "Clean up" echo "=== Decrypt with imported key and PKCS1v15:" test "openssl rsautl -encrypt -inkey pubkey_rsa$k.imported.pem -pubin -in data.txt -out data.enc" "Encryp with OpenSSL" test "$BIN -p password -a decrypt-pkcs1v15 -i $import_keyid --in data.enc --out data.dec" "Decrypt with yubihsm-shell" test "cmp data.txt data.dec" "Compare decrypted data with plain text data" test "rm data.dec" "Clean up" echo "=== Make PKCS10 Certificate Signing Request:" test "openssl req -new -key rsa$k-keypair.pem -subj /CN=test -out csr-ossl.pem" "Generate CSR with OpenSSL" test "$BIN -p password -a generate-csr -i $import_keyid -S /CN=test/ --out csr.pem" "Generate CSR with yubihsm-shell" test "openssl req -in csr.pem -verify" "Verify CSR with openssl" test "cmp csr-ossl.pem csr.pem" "Compare CSRs generated with openssl and yubihsm-shell" test "rm csr.pem csr-ossl.pem" "Clean up" echo "=== Clean up:" test "$BIN -p password -a delete-object -i $keyid -t asymmetric-key" "Delete generated key" test "$BIN -p password -a delete-object -i $import_keyid -t asymmetric-key" "Delete imported key" done echo "****************************************************" echo " Compress X509 Certificate" echo "****************************************************" openssl req -x509 -newkey rsa:4096 -out too_large_cert.pem -sha256 -days 3650 -nodes -subj '/C=01/ST=01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567/L=01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567/O=0123456789012345678901234567890123456789012345678901234567890123/OU=0123456789012345678901234567890123456789012345678901234567890123/CN=0123456789012345678901234567890123456789012345678901234567890123/CN=0123456789012345678901234567890123456789012345678901234567890123' > /dev/null 2>&1 test "$BIN -p password -a put-opaque -i 100 -l too_large_cert -A opaque-x509-certificate --with-compression --in too_large_cert.pem --informat PEM" "Import compressed X509 certificate" test "$BIN -p password -a get-opaque -i 100 --outformat=PEM --out too_large_cert_out.pem" "Read the large certificate from device" test "cmp too_large_cert.pem too_large_cert_out.pem" "Compare read certificate with the one imported" test "$BIN -p password -a delete-object -i 100 -t opaque" "Delete certificate" cd .. rm -rf yubihsm-shell_test_dir set +e set +xyubihsm-shell-2.7.1/resources/tests/bash/cmdline_test.bats0000644000175100017510000017326515133003406023343 0ustar runnerrunnerload 'test_helper/bats-support/load' load 'test_helper/bats-assert/load' setup_file() { echo "--- Configuration via Environment Variables ---" >&3 echo "YUBIHSM_PATH: path to the yubihsm-shell command line tool - using default connector" >&3 echo "SPECIFIED_CONNECTOR: path to the yubihsm-shell command line tool - using specified connector" >&3 echo "TESTS: which tests to run. Possible values are: 'short', 'medium' or 'all'" >&3 echo "It is also possible to individually enable tests by setting the environment variables specified in the README file to 'true'" >&3 echo "-----------------------------------------------" >&3 case "$TESTS" in "all") ED_KEY_TESTS="true" EC_KEY_TESTS="true" RSA_KEY_TESTS="true" HMAC_KEY_TESTS="true" OTP_AEAD_TESTS="true" TEMPLATE_TESTS="true" WRAP_KEY_TESTS="true" LIST_TESTS="true" LABEL_TESTS="true" AUTHENTICATION_TESTS="true" ;; "medium") ED_KEY_TESTS="true" EC_KEY_TESTS="true" HMAC_KEY_TESTS="true" OTP_AEad_TESTS="true" TEMPLATE_TESTS="true" LIST_TESTS="true" LABEL_TESTS="true" AUTHENTICATION_TESTS="true" ;; "short") HMAC_KEY_TESTS="true" OTP_AEAD_TESTS="true" TEMPLATE_TESTS="true" LIST_TESTS="true" LABEL_TESTS="true" AUTHENTICATION_TESTS="true" ;; *) echo "---------------------------------------------------" >&3 echo "Warning: Unrecognized TEST level: '$TESTS'" >&3 echo "Ignore if you are setting individual test variables" >&3 echo "---------------------------------------------------" >&3 ;; esac export ED_KEY_TESTS=${ED_KEY_TESTS:-"false"} export EC_KEY_TESTS=${EC_KEY_TESTS:-"false"} export RSA_KEY_TESTS=${RSA_KEY_TESTS:-"false"} export HMAC_KEY_TESTS=${HMAC_KEY_TESTS:-"false"} export OTP_AEAD_TESTS=${OTP_AEAD_TESTS:-"false"} export TEMPLATE_TESTS=${TEMPLATE_TESTS:-"false"} export WRAP_KEY_TESTS=${WRAP_KEY_TESTS:-"false"} export LIST_TESTS=${LIST_TESTS:-"false"} export LABEL_TESTS=${LABEL_TESTS:-"false"} export AUTHENTICATION_TESTS=${AUTHENTICATION_TESTS:-"false"} local default_bin_path="yubihsm-shell" local os=$(uname -o) export c_var="" if [[ "$os" == "Msys" ]]; then default_bin_path="C:\Program Files\Yubico\YubiHSM Shell\bin\yubihsm-shell.exe" export MSYS2_ARG_CONV_EXCL=* # To prevent path conversion by MSYS2 elif [[ "$os" == "GNU/Linux" || "$os" == "Darwin" ]]; then default_bin_path="/usr/local/bin/yubihsm-shell" fi if [ -n "$SPECIFIED_CONNECTOR" ]; then echo "Specified connector exists" >&3 c_var="-C" fi export BIN=${YUBIHSM_PATH:-$default_bin_path} export SPECIFIED_CONNECTOR=${SPECIFIED_CONNECTOR:-""} echo "Variables Check:" >&3 echo "YubiHSM-shell: $BIN" >&3 echo "Connector: "$c_var" "$SPECIFIED_CONNECTOR"" >&3 echo "Tests to run: $TESTS" >&3 echo "These tests will reset your HSM" >&3 echo "Press Enter to continue or Ctrl-C + enter to abort" >&3 read -p "" if [ -e yubihsm-shell_test_dir ]; then rm -rf yubihsm-shell_test_dir fi mkdir yubihsm-shell_test_dir; cd yubihsm-shell_test_dir echo test signing data > data.txt } @test "Test basic functions and get Pseudo-Random" { command_args=("$BIN" "$c_var" "$SPECIFIED_CONNECTOR") run "${command_args[@]}" -p password -a reset assert_success "HSM was reset" sleep 3 run "${command_args[@]}" --version assert_success "Version works" run "${command_args[@]}" --help assert_success "Help works" run "${command_args[@]}" -a get-device-info assert_success "Get device info" assert_output --partial "Serial number:" run "${command_args[@]}" -p password -a blink assert_success "Blink works" run "${command_args[@]}" -p password -a blink --duration=5 assert_success "Blink with duration works" run "${command_args[@]}" -p password -a get-pseudo-random assert_success output_data=$(echo "$output" | tail -n 1) local byte_count byte_count=$(echo -n "$output_data" | wc -c | xargs) assert_equal "$byte_count" 512 run "${command_args[@]}" -p password -a get-pseudo-random --out=random.txt assert_success "Get Pseudo-Random to file" length=$(cat random.txt | wc -c) if [ "$length" -ne 512 ]; then echo "Expected 512 but was "$length" characters. Without specifying byte count, 256 bytes (=512 characters) pseudo random number should have been produced." >&3 exit 1 fi rm random.txt run "${command_args[@]}" -p password -a get-pseudo-random --count=10 assert_success "Get pseudo-random with --count=10" output_data=$(echo "$output" | tail -n 1) local byte_count byte_count=$(echo -n "$output_data" | wc -c | xargs) assert_equal "$byte_count" 20 run "${command_args[@]}" -p password -a get-pseudo-random --count=10 --out=random.txt assert_success "Get pseudo-random with --count=10" length=$(cat random.txt | wc -c) if [ "$length" -ne 20 ]; then echo "Expected 20 but was "$length" characters." >&3 exit 1 fi rm random.txt } @test "ED Key tests" { [[ "$ED_KEY_TESTS" == "true" ]] || skip "skipping right now" command_args=("$BIN" "$c_var" "$SPECIFIED_CONNECTOR") run "${command_args[@]}" -p password -a reset assert_success "HSM was reset" sleep 3 #Generate run "${command_args[@]}" -p password -a generate-asymmetric-key -i 100 -l \"edKey\" -d 1,2,3 -c sign-eddsa -A ed25519 assert_success "Generate key" run "${command_args[@]}" -p password -a get-object-info -i 100 -t asymmetric-key assert_success "get-object-info" assert_output --partial "id: 0x0064" assert_output --partial "type: asymmetric-key" assert_output --partial "algorithm: ed25519" assert_output --partial 'label: ""edKey""' assert_output --partial "domains: 1:2:3" assert_output --partial "origin: generated" assert_output --partial "capabilities: sign-eddsa" #Get public key run "${command_args[@]}" -p password -a get-public-key -i 100 assert_success "Get public key" "${command_args[@]}" -p password -a get-public-key -i 100 > edkey1.pub 2>/dev/null run "${command_args[@]}" -p password -a get-public-key -i 100 --out edkey2.pub assert_success "Get public key to file" local content1 local content2 content1=$(tr -d '\r' < edkey1.pub) content2=$(tr -d '\r' < edkey2.pub) assert_equal "$content1" "$content2" #Signing run "${command_args[@]}" -p password -a sign-eddsa -i 100 -A ed25519 --in data.txt assert_success "Sign to stdout" "${command_args[@]}" -p password -a sign-eddsa -i 100 -A ed25519 --in data.txt > data.ed1.sig 2>/dev/null run "${command_args[@]}" -p password -a sign-eddsa -i 100 -A ed25519 --in data.txt --out data.ed2.sig assert_success "Sign to file" content1=$(tr -d '[:space:]' < data.ed1.sig) content2=$(tr -d '[:space:]' < data.ed2.sig) assert_equal "$content1" "$content2" #Generating CSR run "${command_args[@]}" -p password -a generate-csr -i 100 -S /CN=test/ --out csr.pem assert_success "Generate CSR with yubihsm-shell" run openssl req -in csr.pem -verify assert_success "Verify CSR with openssl" #Delete run "${command_args[@]}" -p password -a delete-object -i 100 -t asymmetric-key assert_success "Delete key" run rm csr.pem assert_success "Remove CSR" } @test "EC Key tests" { [[ "$EC_KEY_TESTS" == "true" ]] || skip "skipping right now" command_args=("$BIN" "$c_var" "$SPECIFIED_CONNECTOR") genkey=100 import_key=200 run "${command_args[@]}" -p password -a reset assert_success "HSM was reset" sleep 3 EC_ALGOS=("ecp224" "ecp256" "ecp384" "ecp521" "eck256") EC_CURVES=("secp224r1" "secp256r1" "secp384r1" "secp521r1" "secp256k1") if ! grep -q 'Fedora' /etc/os-release 2>/dev/null; then EC_ALGOS+=("ecbp256" "ecbp384" "ecbp512") EC_CURVES+=("brainpoolP256r1" "brainpoolP384r1" "brainpoolP512r1") fi for i in "${!EC_ALGOS[@]}"; do algo=${EC_ALGOS[i]} curve=${EC_CURVES[i]} echo "Testing $algo with curve $curve" >&3 #Generate Key run "${command_args[@]}" -p password -a generate-asymmetric-key -i "$genkey" -l \"ecKey\" -d 5,8,13 -c sign-ecdsa,derive-ecdh,sign-attestation-certificate -A "$algo" assert_success "Generate key" run "${command_args[@]}" -p password -a get-object-info -i "$genkey" -t asymmetric-key assert_success "get-object-info" assert_output --partial "id: 0x0064" assert_output --partial "type: asymmetric-key" assert_output --partial "algorithm: "$algo"" assert_output --partial 'label: ""ecKey""' assert_output --partial "domains: 5:8:13" assert_output --partial "origin: generated" assert_output --partial "capabilities: derive-ecdh:sign-attestation-certificate:sign-ecdsa" run "${command_args[@]}" -p password -a get-public-key -i "$genkey" --outformat=PEM --out "$algo"-gen.pubkey assert_success "Get public key" #Import Key run openssl ecparam -genkey -name "$curve" -noout -out "$curve"-keypair.pem assert_success "Generate key with openssl" run "${command_args[@]}" -p password -a put-asymmetric-key -i "$import_key" -l "ecKeyImport" -d "2,6,7" -c "sign-ecdsa,sign-attestation-certificate" --in="$curve"-keypair.pem assert_success "Import $algo key" run "${command_args[@]}" -p password -a get-object-info -i "$import_key" -t asymmetric-key assert_success "get-object-info" assert_output --partial "id: 0x00c8" assert_output --partial "type: asymmetric-key" assert_output --partial "algorithm: "$algo"" assert_output --partial 'label: "ecKeyImport"' assert_output --partial "domains: 2:6:7" assert_output --partial "origin: imported" assert_output --partial "capabilities: sign-attestation-certificate:sign-ecdsa" run "${command_args[@]}" -p password -a get-public-key -i "$import_key" --outformat=PEM --out "$algo"-import.pubkey assert_success "Get public key" #Signing run "${command_args[@]}" -p password -a sign-ecdsa -i "$genkey" -A ecdsa-sha1 --in data.txt --outformat=PEM --out data."$algo"-sha1gen.sig assert_success "Sign with generated key and ecdsa-sha1" run openssl dgst -sha1 -verify "$algo"-gen.pubkey -signature data."$algo"-sha1gen.sig data.txt assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-ecdsa -i "$genkey" -A ecdsa-sha256 --in data.txt --outformat=PEM --out data."$algo"-sha256gen.sig assert_success "Sign with generated key and ecdsa-sha256" run openssl dgst -sha256 -verify "$algo"-gen.pubkey -signature data."$algo"-sha256gen.sig data.txt assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-ecdsa -i "$genkey" -A ecdsa-sha384 --in data.txt --outformat=PEM --out data."$algo"-sha384gen.sig assert_success "Sign with generated key and ecdsa-sha384" run openssl dgst -sha384 -verify "$algo"-gen.pubkey -signature data."$algo"-sha384gen.sig data.txt assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-ecdsa -i "$genkey" -A ecdsa-sha512 --in data.txt --outformat=PEM --out data."$algo"-sha512gen.sig assert_success "Sign with generated key and ecdsa-sha512" run openssl dgst -sha512 -verify "$algo"-gen.pubkey -signature data."$algo"-sha512gen.sig data.txt assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-ecdsa -i "$import_key" -A ecdsa-sha1 --in data.txt --outformat=PEM --out data."$algo"-sha1import.sig assert_success "Sign with imported key and ecdsa-sha1" run openssl dgst -sha1 -verify "$algo"-import.pubkey -signature data."$algo"-sha1import.sig data.txt assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-ecdsa -i "$import_key" -A ecdsa-sha256 --in data.txt --outformat=PEM --out data."$algo"-sha256import.sig assert_success "Sign with imported key and ecdsa-sha256" run openssl dgst -sha256 -verify "$algo"-import.pubkey -signature data."$algo"-sha256import.sig data.txt assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-ecdsa -i "$import_key" -A ecdsa-sha384 --in data.txt --outformat=PEM --out data."$algo"-sha384import.sig assert_success "Sign with imported key and ecdsa-sha384" run openssl dgst -sha384 -verify "$algo"-import.pubkey -signature data."$algo"-sha384import.sig data.txt assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-ecdsa -i "$import_key" -A ecdsa-sha512 --in data.txt --outformat=PEM --out data."$algo"-sha512import.sig assert_success "Sign with imported key and ecdsa-sha512" run openssl dgst -sha512 -verify "$algo"-import.pubkey -signature data."$algo"-sha512import.sig data.txt assert_success "Verify signature with openssl" #Get attestation certificate and selfsigned certificate if "${command_args[@]}" -p password -a sign-attestation-certificate -i "$genkey" --attestation-id 0 2>&1 > /dev/null;then # Some YubiHSMs does not have default attestation certificate run "${command_args[@]}" -p password -a sign-attestation-certificate -i "$genkey" --attestation-id 0 --out cert.pem assert_success "Sign attestation cert with default key" run openssl x509 -in cert.pem -out cert.der -outform DER assert_success "Convert cert format" run "${command_args[@]}" -p password -a put-opaque -i "$genkey" -l template_cert -A opaque-x509-certificate --in cert.der assert_success "Import attestation cert as template cert (same ID as generated key)" run "${command_args[@]}" -p password -a put-opaque -i "$import_key" -l template_cert -A opaque-x509-certificate --in cert.der assert_success "Import attestation cert as template cert (same ID as imported key)" run rm cert.der assert_success "Remove der cert" else run "${command_args[@]}" -p password -a put-opaque -i "$genkey" -l template_cert_gen -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem assert_success "Import attestation cert as template cert (same ID as generated key)" run "${command_args[@]}" -p password -a put-opaque -i "$import_key" -l template_cert_imp -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem assert_success "Import attestation cert as template cert (same ID as imported key)" fi run "${command_args[@]}" -p password -a sign-attestation-certificate -i "$genkey" --attestation-id="$genkey" --out selfsigned_cert.pem assert_success "Get selfsigned certificate" run "${command_args[@]}" -p password -a delete-object -i "$genkey" -t opaque assert_success "Delete template certificate" run "${command_args[@]}" -p password -a put-opaque -i "$genkey" -l java_cert -A opaque-x509-certificate --informat=PEM --in selfsigned_cert.pem assert_success "Import selfsigned with same key ID" run rm selfsigned_cert.pem assert_success "Remove selfsigned cert" #Sign attestation certificate run "${command_args[@]}" -p password -a sign-attestation-certificate -i "$genkey" --attestation-id="$import_key" --out selfsigned_cert.pem assert_success "Sign attestation cert with imported key" run "${command_args[@]}" -p password -a delete-object -i "$genkey" -t opaque assert_success "Delete template certificate" run "${command_args[@]}" -p password -a delete-object -i "$import_key" -t opaque assert_success "Delete template certificate" run rm selfsigned_cert.pem assert_success "Remove selfsigned cert" #Derive ECDH run openssl ec -in "$curve"-keypair.pem -pubout -out "$curve"-pubkey.pem assert_success "Get imported key public key with OpenSSL" run "${command_args[@]}" -p password -a derive-ecdh -i "$genkey" --in "$curve"-pubkey.pem --outformat binary --out "$algo"-ecdh-shell.key assert_success "Derive ECDH key with yubihsm-shell" run openssl pkeyutl -derive -inkey "$curve"-keypair.pem -peerkey "$algo"-gen.pubkey -out "$algo"-ecdh-openssl.key assert_success "Derive ECDH key with OpenSSL" run cmp "$algo"-ecdh-shell.key "$algo"-ecdh-openssl.key assert_success "Compare derived keys" #make PKCS10 certificate signing request run "${command_args[@]}" -p password -a generate-csr -i "$genkey" -S /CN=test/ --out csr.pem assert_success "Generate CSR with yubihsm-shell" run openssl req -in csr.pem -verify assert_success "Verify CSR with openssl" run rm csr.pem assert_success "Remove CSR" #Clean up run "${command_args[@]}" -p password -a delete-object -i "$genkey" -t asymmetric-key assert_success "Delete generated key" run "${command_args[@]}" -p password -a delete-object -i "$import_key" -t asymmetric-key assert_success "Delete imported key" done } @test "RSA Key tests" { [[ "$RSA_KEY_TESTS" == "true" ]] || skip "skipping right now" command_args=("$BIN" "$c_var" "$SPECIFIED_CONNECTOR") RSA_KEYSIZE=("2048" "3072" "4096") run "${command_args[@]}" -p password -a reset assert_success "HSM was reset" sleep 3 for k in ${RSA_KEYSIZE[@]}; do echo "Testing RSA "$k" key" >&3 if [ "$k" -ne "2048" ]; then echo "This may take a while..." >&3 fi #Generate Key run "${command_args[@]}" -p password -a generate-asymmetric-key -i 0 -l rsaKey -d 1 -c sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate -A rsa"$k" assert_success "Generate RSA "$k" key" keyid=$(echo "$output" | tail -n 1 | awk '{print $4}') run "${command_args[@]}" -p password -a get-object-info -i "$keyid" -t asymmetric-key assert_success "get-object-info" assert_output --partial "id: "$keyid"" assert_output --partial "type: asymmetric-key" assert_output --partial "algorithm: rsa"$k"" assert_output --partial "label: \"rsaKey\"" assert_output --partial "domains: 1" assert_output --partial "origin: generated" assert_output --partial "decrypt-oaep:decrypt-pkcs:sign-attestation-certificate:sign-pkcs:sign-pss" run "${command_args[@]}" -p password -a get-public-key -i "$keyid" --outformat=PEM --out pubkey_rsa"$k".pem assert_success "Get public key" #Import key run openssl genrsa -out rsa"$k"-keypair.pem "$k" assert_success "Generate key with OpenSSL" run "${command_args[@]}" "${command_args[@]}" -p password -a put-asymmetric-key -i 0 -l rsaKeyImport -d 2 -c sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate --in=rsa"$k"-keypair.pem assert_success "Import key" import_keyid=$(echo "$output" | tail -n 1 | awk '{print $4}') run "${command_args[@]}" -p password -a get-object-info -i "$import_keyid" -t asymmetric-key assert_success "get-object-info" assert_output --partial "id: "$import_keyid"" assert_output --partial "type: asymmetric-key" assert_output --partial "algorithm: rsa"$k"" assert_output --partial "label: \"rsaKeyImport\"" assert_output --partial "domains: 2" assert_output --partial "origin: imported" assert_output --partial "decrypt-oaep:decrypt-pkcs:sign-attestation-certificate:sign-pkcs:sign-pss" run "${command_args[@]}" -p password -a get-public-key -i "$import_keyid" --outformat=PEM --out pubkey_rsa"$k".imported.pem assert_success "Get public key" #Signing with generated key run "${command_args[@]}" -p password -a sign-pkcs1v15 -i "$keyid" -A rsa-pkcs1-sha1 --in data.txt --outformat binary --out data."$k"-pkcs1sha1gen.sig assert_success "Sign with rsa-pkcs1-sha1" run openssl dgst -sha1 -verify pubkey_rsa"$k".pem -signature data."$k"-pkcs1sha1gen.sig data.txt assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-pkcs1v15 -i "$keyid" -A rsa-pkcs1-sha256 --in data.txt --outformat binary --out data."$k"-pkcs1sha256gen.sig assert_success "Sign with rsa-pkcs1-sha256" run openssl dgst -sha256 -verify pubkey_rsa"$k".pem -signature data."$k"-pkcs1sha256gen.sig data.txt assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-pkcs1v15 -i "$keyid" -A rsa-pkcs1-sha384 --in data.txt --outformat binary --out data."$k"-pkcs1sha384gen.sig assert_success "Sign with rsa-pkcs1-sha384" run openssl dgst -sha384 -verify pubkey_rsa"$k".pem -signature data."$k"-pkcs1sha384gen.sig data.txt assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-pkcs1v15 -i "$keyid" -A rsa-pkcs1-sha512 --in data.txt --outformat binary --out data."$k"-pkcs1sha512gen.sig assert_success "Sign with rsa-pkcs1-sha512" run openssl dgst -sha512 -verify pubkey_rsa"$k".pem -signature data."$k"-pkcs1sha512gen.sig data.txt assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-pss -i "$keyid" -A rsa-pss-sha1 --in data.txt --outformat binary --out data."$k"-psssha1gen.sig assert_success "Sign with rsa-pss-sha1" run openssl dgst -sha1 -binary -out data.sha1 data.txt assert_success "Hash data with openssl" run openssl pkeyutl -verify -in data.sha1 -sigfile data."$k"-psssha1gen.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_rsa"$k".pem -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha1 assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-pss -i "$keyid" -A rsa-pss-sha256 --in data.txt --outformat binary --out data."$k"-psssha256gen.sig assert_success "Sign with rsa-pss-sha256" run openssl dgst -sha256 -binary -out data.sha256 data.txt assert_success "Hash data with openssl" run openssl pkeyutl -verify -in data.sha256 -sigfile data."$k"-psssha256gen.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_rsa"$k".pem -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha256 assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-pss -i "$keyid" -A rsa-pss-sha384 --in data.txt --outformat binary --out data."$k"-psssha384gen.sig assert_success "Sign with rsa-pss-sha384" run openssl dgst -sha384 -binary -out data.sha384 data.txt assert_success "Hash data with openssl" run openssl pkeyutl -verify -in data.sha384 -sigfile data."$k"-psssha384gen.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_rsa"$k".pem -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha384 assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-pss -i "$keyid" -A rsa-pss-sha512 --in data.txt --outformat binary --out data."$k"-psssha512gen.sig assert_success "Sign with rsa-pss-sha512" run openssl dgst -sha512 -binary -out data.sha512 data.txt assert_success "Hash data with openssl" run openssl pkeyutl -verify -in data.sha512 -sigfile data."$k"-psssha512gen.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_rsa"$k".pem -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha512 assert_success "Verify signature with openssl" #Signing with imported key run "${command_args[@]}" -p password -a sign-pkcs1v15 -i "$import_keyid" -A rsa-pkcs1-sha1 --in data.txt --outformat binary --out data."$k"-pkcs1sha1import.sig assert_success "Sign with rsa-pkcs1-sha1" run openssl dgst -sha1 -verify pubkey_rsa"$k".imported.pem -signature data."$k"-pkcs1sha1import.sig data.txt assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-pkcs1v15 -i "$import_keyid" -A rsa-pkcs1-sha256 --in data.txt --outformat binary --out data."$k"-pkcs1sha256import.sig assert_success "Sign with rsa-pkcs1-sha256" run openssl dgst -sha256 -verify pubkey_rsa"$k".imported.pem -signature data."$k"-pkcs1sha256import.sig data.txt assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-pkcs1v15 -i "$import_keyid" -A rsa-pkcs1-sha384 --in data.txt --outformat binary --out data."$k"-pkcs1sha384import.sig assert_success "Sign with rsa-pkcs1-sha384" run openssl dgst -sha384 -verify pubkey_rsa"$k".imported.pem -signature data."$k"-pkcs1sha384import.sig data.txt assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-pkcs1v15 -i "$import_keyid" -A rsa-pkcs1-sha512 --in data.txt --outformat binary --out data."$k"-pkcs1sha512import.sig assert_success "Sign with rsa-pkcs1-sha512" run openssl dgst -sha512 -verify pubkey_rsa"$k".imported.pem -signature data."$k"-pkcs1sha512import.sig data.txt assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-pss -i "$import_keyid" -A rsa-pss-sha1 --in data.txt --outformat binary --out data."$k"-psssha1import.sig assert_success "Sign with rsa-pss-sha1" run openssl dgst -sha1 -binary -out data.sha1 data.txt assert_success "Hash data with openssl" run openssl pkeyutl -verify -in data.sha1 -sigfile data."$k"-psssha1import.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_rsa"$k".imported.pem -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha1 assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-pss -i "$import_keyid" -A rsa-pss-sha256 --in data.txt --outformat binary --out data."$k"-psssha256import.sig assert_success "Sign with rsa-pss-sha256" run openssl dgst -sha256 -binary -out data.sha256 data.txt assert_success "Hash data with openssl" run openssl pkeyutl -verify -in data.sha256 -sigfile data."$k"-psssha256import.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_rsa"$k".imported.pem -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha256 assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-pss -i "$import_keyid" -A rsa-pss-sha384 --in data.txt --outformat binary --out data."$k"-psssha384import.sig assert_success "Sign with rsa-pss-sha384" run openssl dgst -sha384 -binary -out data.sha384 data.txt assert_success "Hash data with openssl" run openssl pkeyutl -verify -in data.sha384 -sigfile data."$k"-psssha384import.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_rsa"$k".imported.pem -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha384 assert_success "Verify signature with openssl" run "${command_args[@]}" -p password -a sign-pss -i "$import_keyid" -A rsa-pss-sha512 --in data.txt --outformat binary --out data."$k"-psssha512import.sig assert_success "Sign with rsa-pss-sha512" run openssl dgst -sha512 -binary -out data.sha512 data.txt assert_success "Hash data with openssl" run openssl pkeyutl -verify -in data.sha512 -sigfile data."$k"-psssha512import.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_rsa"$k".imported.pem -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha512 assert_success "Verify signature with openssl" #Make self signed certificate if "${command_args[@]}" -p password -a sign-attestation-certificate -i "$keyid" --attestation-id 0 2>&1 > /dev/null;then #Some YubiHSMs does not have default attestation certificate run "${command_args[@]}" -p password -a sign-attestation-certificate -i "$keyid" --attestation-id 0 --out cert.pem assert_success "Sign attestation cert with default key" run openssl x509 -in cert.pem -out cert.der -outform DER assert_success "Convert cert format" run "${command_args[@]}" -p password -a put-opaque -i "$keyid" -l template_cert -A opaque-x509-certificate --in cert.der assert_success "Import attestation cert as template cert (same ID as generated key)" run "${command_args[@]}" -p password -a put-opaque -i "$import_keyid" -l template_cert -A opaque-x509-certificate --in cert.der assert_success "Import attestation cert as template cert (same ID as imported key)" run rm cert.der assert_success "Remove der cert" else run "${command_args[@]}" -p password -a put-opaque -i "$keyid" -l template_cert_gen -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem assert_success "Import attestation cert as template cert (same ID as generated key)" run "${command_args[@]}" -p password -a put-opaque -i "$import_keyid" -l template_cert_imp -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem assert_success "Import attestation cert as template cert (same ID as imported key)" fi run "${command_args[@]}" -p password -a sign-attestation-certificate -i "$keyid" --attestation-id="$keyid" --out selfsigned_cert.pem assert_success "Sign attestation with same key (aka. get selfsigned cert)" run "${command_args[@]}" -p password -a delete-object -i "$keyid" -t opaque assert_success "Delete template certificate" run "${command_args[@]}" -p password -a put-opaque -i "$keyid" -l java_cert -A opaque-x509-certificate --informat=PEM --in selfsigned_cert.pem assert_success "Import selfsigned with same key ID" run rm selfsigned_cert.pem assert_success "Remove selfsigned cert" #Sign attestation certificate run "${command_args[@]}" -p password -a sign-attestation-certificate -i "$keyid" --attestation-id="$import_keyid" --out selfsigned_cert.pem assert_success "Sign attestation cert with imported key" run rm selfsigned_cert.pem assert_success "Remove selfsigned cert" run "${command_args[@]}" -p password -a delete-object -i "$import_keyid" -t opaque assert_success "Delete template certificate" run "${command_args[@]}" -p password -a delete-object -i "$keyid" -t opaque assert_success "Delete template certificate" #Decryption with generated key and PKCS1v15 run openssl rsautl -encrypt -inkey pubkey_rsa"$k".pem -pubin -in data.txt -out data.enc assert_success "Encrypt data with openssl" run "${command_args[@]}" -p password -a decrypt-pkcs1v15 -i "$keyid" --in data.enc --out data.dec assert_success "Decrypt data with yubihsm-shell" run cmp data.txt data.dec assert_success "Compare decrypted data with plain text data" run rm data.dec assert_success "Remove decrypted data" #Decryption with imported key and PKCS1v15 run openssl rsautl -encrypt -inkey pubkey_rsa"$k".imported.pem -pubin -in data.txt -out data.enc assert_success "Encrypt data with openssl" run "${command_args[@]}" -p password -a decrypt-pkcs1v15 -i "$import_keyid" --in data.enc --out data.dec assert_success "Decrypt data with yubihsm-shell" run cmp data.txt data.dec assert_success "Compare decrypted data with plain text data" run rm data.dec assert_success "Remove decrypted data" #Make PKCS10 Certificate Signing Request run openssl req -new -key rsa$k-keypair.pem -subj /CN=test -out csr-ossl.pem assert_success "Generate CSR with OpenSSL" run "${command_args[@]}" -p password -a generate-csr -i "$import_keyid" -S /CN=test/ --out csr.pem assert_success "Generate CSR with yubihsm-shell" run openssl req -in csr.pem -verify assert_success "Verify CSR with openssl" run cmp csr-ossl.pem csr.pem assert_success "Compare CSR with OpenSSL generated CSR" run rm csr.pem csr-ossl.pem assert_success "Remove CSR" #Clean up run "${command_args[@]}" -p password -a delete-object -i "$keyid" -t asymmetric-key assert_success "Delete generated key" run "${command_args[@]}" -p password -a delete-object -i "$import_keyid" -t asymmetric-key assert_success "Delete imported key" done run openssl req -x509 -newkey rsa:4096 -out too_large_cert.pem -sha256 -days 3650 -nodes -subj '/C=01/ST=01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567/L=01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567/O=0123456789012345678901234567890123456789012345678901234567890123/OU=0123456789012345678901234567890123456789012345678901234567890123/CN=0123456789012345678901234567890123456789012345678901234567890123/CN=0123456789012345678901234567890123456789012345678901234567890123' > /dev/null 2>&1 assert_success "Generate too large certificate with OpenSSL" run "${command_args[@]}" -p password -a put-opaque -i 100 -l too_large_cert -A opaque-x509-certificate --in too_large_cert.pem --informat PEM if [ "$status" -eq 0 ]; then assert_success "Import large certificate raw" echo "Imported x509 certificate raw" >&3 elif [[ "$output" == *"Failed to store opaque object: Not enough space to store data"* ]]; then run "${command_args[@]}" -p password -a put-opaque -i 100 -l too_large_cert -A opaque-x509-certificate --with-compression --in too_large_cert.pem --informat PEM assert_success "Import compressed x509 certificate" echo "Imported compressed x509 Certificate" >&3 else fail "Import of x509 certificate failed" fi run "${command_args[@]}" -p password -a get-opaque -i 100 --outformat=PEM --out too_large_cert_out.pem assert_success "Get too large certificate" run cmp too_large_cert.pem too_large_cert_out.pem assert_success "Compare imported and read certificate" run "${command_args[@]}" -p password -a delete-object -i 100 -t opaque assert_success "Delete too large certificate" } @test "HMAC Key tests" { [[ "$HMAC_KEY_TESTS" == "true" ]] || skip "skipping right now" command_args=("$BIN" "$c_var" "$SPECIFIED_CONNECTOR") algorithms=("hmac-sha1" "hmac-sha256" "hmac-sha384" "hmac-sha512") run "${command_args[@]}" -p password -a reset assert_success "HSM was reset" sleep 3 for algo in ${algorithms[@]}; do echo "$algo" >&3 run "${command_args[@]}" -p password -a generate-hmac-key -i 0 -l hmackey -d 1,2,3 -c sign-hmac -A "$algo" assert_success "Generate "$algo" key" keyid=$(echo "$output" | tail -n 1 | awk '{print $4}') run "${command_args[@]}" -p password -a get-object-info -i "$keyid" -t hmac-key assert_success "get-object-info" assert_output --partial "id: "$keyid"" assert_output --partial "type: hmac-key" assert_output --partial "algorithm: "$algo"" assert_output --partial "label: \"hmackey\"" assert_output --partial "domains: 1:2:3" assert_output --partial "origin: generated" assert_output --partial "sign-hmac" done } @test "OTP AEAD Key tests" { [[ "$OTP_AEAD_TESTS" == "true" ]] || skip "skipping right now" command_args=("$BIN" "$c_var" "$SPECIFIED_CONNECTOR") algorithms=("aes128" "aes192" "aes256") run "${command_args[@]}" -p password -a reset assert_success "HSM was reset" sleep 3 for algo in ${algorithms[@]}; do echo "$algo" >&3 run "${command_args[@]}" -p password -a generate-otp-aead-key -i 0 -l aeadkey -d 1,2,3 -c randomize-otp-aead -A "$algo"-yubico-otp --nonce 0x01020304 assert_success "Generate Key" keyid=$(echo "$output" | tail -n 1 | awk '{print $5}') run "${command_args[@]}" -p password -a get-object-info -i "$keyid" -t otp-aead-key assert_success "Get object info" assert_output --partial "id: "$keyid"" assert_output --partial "type: otp-aead-key" assert_output --partial "algorithm: "$algo"-yubico-otp" assert_output --partial "label: \"aeadkey\"" assert_output --partial "domains: 1:2:3" assert_output --partial "origin: generated" assert_output --partial "capabilities: randomize-otp-aead" run "${command_args[@]}" -p password -a randomize-otp-aead -i "$keyid" assert_success "Randomize OTP AEAD" run "${command_args[@]}" -p password -a delete-object -i "$keyid" -t otp-aead-key assert_success "Delete key" done } @test "Template tests" { [[ "$TEMPLATE_TESTS" == "true" ]] || skip "skipping right now" command_args=("$BIN" "$c_var" "$SPECIFIED_CONNECTOR") run "${command_args[@]}" -p password -a reset assert_success "HSM was reset" sleep 3 run "${command_args[@]}" -p password -a put-template -i 20 -l "SSH_Template" -d 1 -A template-ssh --in ../template.dat assert_success "Import template" id=$(echo "$output" | grep "Stored Template object" | awk '{print $4}') run "${command_args[@]}" -p password -a get-object-info -i "$id" -t template assert_success "Get object info" assert_output --partial "id: "$id"" assert_output --partial "type: template" assert_output --partial "algorithm: template-ssh" assert_output --partial "label: \"SSH_Template\"" assert_output --partial "domains: 1" assert_output --partial "origin: imported" #This command doesn't work right now. #run "${command_args[@]}" --authkey=0x0001 -p password -a sign-ssh-certificate -i 10 --template-id 20 -A rsa-pkcs1-sha256 --in ../req.dat --out ./id_rsa-cert.pub #assert_success "sign request" run "${command_args[@]}" -p password -a get-template -i "$id" assert_success "Get template" run "${command_args[@]}" -p password -a delete-object -i "$id" -t template assert_success "Delete template" } @test "Wrap Keys tests" { [[ "$WRAP_KEY_TESTS" == "true" ]] || skip "skipping right now" command_args=("$BIN" "$c_var" "$SPECIFIED_CONNECTOR") algorithms=("aes128-ccm-wrap" "aes192-ccm-wrap" "aes256-ccm-wrap") eckey=100 aeskey=200 sequence=0 RSA_KEYSIZE=("2048" "3072" "4096") seq_ec=6 seq_aes=0 aes_enabled=false run "${command_args[@]}" -p password -a reset assert_success "HSM was reset" sleep 3 run "${command_args[@]}" -p password -a generate-asymmetric-key -i "$eckey" -l eckey -d 1 -c exportable-under-wrap,sign-ecdsa -A ecp224 assert_success "Generate EC Key to wrap" run "${command_args[@]}" -p password -a get-object-info -i "$eckey" -t asymmetric-key assert_success "Get object info" assert_output --partial "sequence: "$sequence"" sequence=$((sequence+1)) assert_output --partial "origin: generated" for algo in ${algorithms[@]}; do echo "$algo" >&3 length=24 import_count=16 if [ "$algo" == "aes192-ccm-wrap" ]; then length=32 import_count=24 elif [ "$algo" == "aes256-ccm-wrap" ]; then length=40 import_count=32 fi #Generate key run "${command_args[@]}" -p password -a generate-wrap-key -i 0 -l wrapkey -d 1 -c export-wrapped,import-wrapped --delegated sign-ecdsa,exportable-under-wrap -A "$algo" assert_success "Generate wrap key" keyid=$(echo "$output" | awk '/Generated Wrap key/ {print $4}') run "${command_args[@]}" -p password -a get-object-info -i "$keyid" -t wrap-key assert_success "Get object info" assert_output --partial "algorithm: "$algo"" assert_output --partial "length: "$length"" #Import key run "${command_args[@]}" -p password -a get-pseudo-random --count "$import_count" assert_success "Get random 16 bytes" wrapkey=$(echo "$output" | tail -n 1) run "${command_args[@]}" -p password -a put-wrap-key -i 0 -l imported_wrapkey -d 1 -c export-wrapped,import-wrapped --delegated sign-ecdsa,exportable-under-wrap --in="$wrapkey" assert_success "Import wrap key" import_keyid=$(echo "$output" | awk '/Stored Wrap key/ {print $4}') run "${command_args[@]}" -p password -a get-object-info -i "$import_keyid" -t wrap-key assert_success "Get object info" assert_output --partial "algorithm: "$algo"" assert_output --partial "length: "$length"" assert_output --partial "origin: imported" #Wrap and unwrap with generated wrap key run "${command_args[@]}" -p password -a get-wrapped --wrap-id "$keyid" -i 100 -t asymmetric-key --out key.gen_wrapped assert_success "Wrap EC key" run "${command_args[@]}" -p password -a delete-object -i "$eckey" -t asymmetric-key assert_success "Delete EC key" run "${command_args[@]}" -p password -a put-wrapped --wrap-id "$keyid" --in key.gen_wrapped assert_success "Wrap EC key" run "${command_args[@]}" -p password -a get-object-info -i "$eckey" -t asymmetric-key assert_success "Get object info" assert_output --partial "sequence: "$sequence"" sequence=$((sequence+1)) assert_output --partial "origin: generated:imported_wrapped" assert_output --partial "capabilities: exportable-under-wrap:sign-ecdsa" run "${command_args[@]}" -p password -a sign-ecdsa -i "$eckey" -A ecdsa-sha1 --in data.txt assert_success "Perform signature with imported wrapped key" #Wrap and unwrap objects with imported wrap key run "${command_args[@]}" -p password -a get-wrapped --wrap-id "$import_keyid" -i 100 -t asymmetric-key --out key.imp_wrapped assert_success "Wrap EC key" run "${command_args[@]}" -p password -a delete-object -i "$eckey" -t asymmetric-key assert_success "Delete EC key" run "${command_args[@]}" -p password -a put-wrapped --wrap-id "$import_keyid" --in key.imp_wrapped assert_success "Wrap EC key" run "${command_args[@]}" -p password -a get-object-info -i "$eckey" -t asymmetric-key assert_success "Get object info" assert_output --partial "sequence: "$sequence"" sequence=$((sequence+1)) assert_output --partial "origin: generated:imported_wrapped" assert_output --partial "capabilities: exportable-under-wrap:sign-ecdsa" run "${command_args[@]}" -p password -a sign-ecdsa -i "$eckey" -A ecdsa-sha1 --in data.txt assert_success "Perform signature with imported wrapped key" #Clean up run "${command_args[@]}" -p password -a delete-object -i "$keyid" -t wrap-key assert_success "Delete generated wrap key" run "${command_args[@]}" -p password -a delete-object -i "$import_keyid" -t wrap-key assert_success "Delete imported wrap key" run rm key.gen_wrapped key.imp_wrapped assert_success "Deleted generated and imported wrap keys" done run "${command_args[@]}" -p password -a get-device-info assert_success "Get device info" if [[ "$output" != *"aes-kwp"* ]]; then run "${command_args[@]}" -p password -a delete-object -i "$eckey" -t asymmetric-key assert_success "Delete object" skip "Device does not support aes-kwp, skipping these tests." fi run "${command_args[@]}" -p password -a get-device-info assert_success "Get device info" if [[ "$output" == *"aes-cbc"* ]]; then aes_enabled=true run "${command_args[@]}" -p password -a generate-symmetric-key -i "$aeskey" -l aeskey -d 1 -c exportable-under-wrap,encrypt-cbc,decrypt-cbc -A aes128 assert_success "Generate AES key to wrap" run "${command_args[@]}" -p password -a get-pseudo-random --count 16 assert_success "Get random 16 bytes" iv=$(echo "$output" | tail -n 1) run "${command_args[@]}" -p password -a get-pseudo-random --count 32 assert_success "Get random 32 bytes for encryption" data=$(echo "$output" | tail -n 1) fi for k in ${RSA_KEYSIZE[@]}; do echo "RSA"$k"" >&3 if [[ "$k" != "2048" ]]; then echo "This may take a while..." >&3 fi #Generate RSA wrap keys run "${command_args[@]}" -p password -a generate-wrap-key -i 0 -l wrapkey -c import-wrapped --delegated exportable-under-wrap,sign-ecdsa,encrypt-cbc,decrypt-cbc -A rsa"$k" assert_success "Generate RSA wrap key" keyid=$(echo "$output" | awk '/Generated Wrap key/ {print $4}') run "${command_args[@]}" -p password -a get-object-info -i "$keyid" -t wrap-key assert_success "Get object into" assert_output --partial "algorithm: rsa"$k"" assert_output --partial "origin: generated" run "${command_args[@]}" -p password -a get-public-key -i "$keyid" -t wrap-key --out public_wrapkey.pem assert_success "Export rsa public wrap key" run "${command_args[@]}" -p password -a put-public-wrapkey -i "$keyid" -c export-wrapped --delegated exportable-under-wrap,sign-ecdsa,encrypt-cbc,decrypt-cbc --in public_wrapkey.pem assert_success "Import RSA public wrap key" run rm public_wrapkey.pem assert_success "Delete wrapkey" #Wrap and unwrap EC object with generated wrap key run "${command_args[@]}" -p password -a get-rsa-wrapped --wrap-id "$keyid" -i "$eckey" -t asymmetric-key --out rsawrapped.object assert_success "Export wrapped EC object" run "${command_args[@]}" -p password -a delete-object -i "$eckey" -t asymmetric-key assert_success "Delete EC key" run "${command_args[@]}" -p password -a put-rsa-wrapped --wrap-id "$keyid" --in rsawrapped.object assert_success "Import wrapped EC object" run "${command_args[@]}" -p password -a get-object-info -i "$eckey" -t asymmetric-key assert_success "Get object info" seq_ec=$((seq_ec+1)) assert_output --partial "sequence: "$seq_ec"" assert_output --partial "capabilities: exportable-under-wrap:sign-ecdsa" run "${command_args[@]}" -p password -a sign-ecdsa -i "$eckey" -A ecdsa-sha1 --in data.txt assert_success "Perform signature with imported wrapped EC key" run rm rsawrapped.object assert_success "Removed RSA wrapped object" #Wrap and unwrap EC key material with generated RSA wrap key run "${command_args[@]}" -p password -a get-rsa-wrapped-key --wrap-id "$keyid" -i "$eckey" -t asymmetric-key --oaep rsa-oaep-sha1 --mgf1 mgf1-sha384 --out rsawrapped.key assert_success "Export wrapped EC key material" run "${command_args[@]}" -p password -a delete-object -i "$eckey" -t asymmetric-key assert_success "Delete EC key" run "${command_args[@]}" -p password -a put-rsa-wrapped-key --wrap-id "$keyid" -i "$eckey" -t asymmetric-key -A ecp224 -c exportable-under-wrap,sign-ecdsa --oaep rsa-oaep-sha1 --mgf1 mgf1-sha384 --in rsawrapped.key assert_success "Import wrapped EC key material" run "${command_args[@]}" -p password -a get-object-info -i "$eckey" -t asymmetric-key assert_success "Get object info" seq_ec=$((seq_ec+1)) assert_output --partial "sequence: "$seq_ec"" assert_output --partial "origin: imported:imported_wrapped" assert_output --partial "capabilities: exportable-under-wrap:sign-ecdsa" run "${command_args[@]}" -p password -a sign-ecdsa -i "$eckey" -A ecdsa-sha1 --in data.txt assert_success "Perform signature with imported wrapped EC key" run rm rsawrapped.key assert_success "Removed RSA wrapped key" if [[ "$aes_enabled" = true ]]; then #Wrap and unwrap AES object with generated RSA wrap key run "${command_args[@]}" -p password -a get-rsa-wrapped --wrap-id "$keyid" -i "$aeskey" -t symmetric-key --out rsawrapped.object assert_success "Export wrapped AES object" run "${command_args[@]}" -p password -a delete-object -i "$aeskey" -t symmetric-key assert_success "Delete AES key" run "${command_args[@]}" -p password -a put-rsa-wrapped --wrap-id "$keyid" --in rsawrapped.object assert_success "Import wrapped AES object" run "${command_args[@]}" -p password -a get-object-info -i "$aeskey" -t symmetric-key assert_success "Get object info" seq_aes=$((seq_aes+1)) assert_output --partial "sequence: "$seq_aes"" assert_output --partial "capabilities: decrypt-cbc:encrypt-cbc:exportable-under-wrap" run "${command_args[@]}" -p password -a encrypt-aescbc -i "$aeskey" --iv "$iv" --in "$data" --out data.enc assert_success "Perform encryption with imported wrapped AES key" run "${command_args[@]}" -p password -a decrypt-aescbc -i "$aeskey" --iv "$iv" --in data.enc decrypted_data=$(echo "$output" | tail -n 1) assert_equal "$decrypted_data" "$data" assert_success "Perform decryption with imported wrapped AES key" run rm rsawrapped.object data.enc assert_success "Removed RSA wrapped object and encrypted data" #Wrap and unwrap AES key material with generated RSA wrap key run "${command_args[@]}" -p password -a get-rsa-wrapped-key --wrap-id "$keyid" -i "$aeskey" -t symmetric-key --oaep rsa-oaep-sha384 --mgf1 mgf1-sha1 --out rsawrapped.key assert_success "Export wrapped AES key material" run "${command_args[@]}" -p password -a delete-object -i "$aeskey" -t symmetric-key assert_success "Delete AES key" run "${command_args[@]}" -p password -a put-rsa-wrapped-key --wrap-id "$keyid" -i "$aeskey" -t symmetric-key -A aes128 -c exportable-under-wrap,decrypt-cbc,encrypt-cbc --oaep rsa-oaep-sha384 --mgf1 mgf1-sha1 --in rsawrapped.key assert_success "Import wrapped AES key material" run "${command_args[@]}" -p password -a get-object-info -i "$aeskey" -t symmetric-key assert_success "Get object info" seq_aes=$((seq_aes+1)) assert_output --partial "sequence: "$seq_aes"" assert_output --partial "origin: imported:imported_wrapped" assert_output --partial "capabilities: decrypt-cbc:encrypt-cbc:exportable-under-wrap" run "${command_args[@]}" -p password -a sign-ecdsa -i "$eckey" -A ecdsa-sha1 --in data.txt assert_success "Perform signature with imported wrapped EC key" run "${command_args[@]}" -p password -a encrypt-aescbc -i "$aeskey" --iv "$iv" --in "$data" --out data.enc assert_success "Perform encryption with imported wrapped AES key" run "${command_args[@]}" -p password -a decrypt-aescbc -i "$aeskey" --iv "$iv" --in data.enc assert_success "Perform decryption with imported wrapped AES key" run "${command_args[@]}" -p password -a decrypt-aescbc -i "$aeskey" --iv "$iv" --in data.enc assert_success "Decryption succeeded" last_line_of_output=$(echo "$output" | tail -n 1) assert_equal "$last_line_of_output" "$data" run rm rsawrapped.key data.enc assert_success "Removed RSA wrapped key and encrypted data" fi #Import RSA wrap keys run openssl genrsa -out keypair.pem "$k" assert_success "Generate RSA key with openssl" run openssl rsa -in keypair.pem -pubout -out key.pub assert_success "Extract public key from openssl generated keypair" run "${command_args[@]}" -p password -a put-rsa-wrapkey -i 0 -d 1 -c import-wrapped --delegated exportable-under-wrap,sign-ecdsa,encrypt-cbc,decrypt-cbc --in keypair.pem assert_success "Import RSA wrap key" import_keyid=$(echo "$output" | awk '/Stored Wrap key/ {print $4}') run "${command_args[@]}" -p password -a get-object-info -i "$import_keyid" -t wrap-key assert_success "Get object info" assert_output --partial "algorithm: rsa"$k"" assert_output --partial "origin: imported" run "${command_args[@]}" -p password -a put-public-wrapkey -i "$import_keyid" -c export-wrapped --delegated exportable-under-wrap,sign-ecdsa,encrypt-cbc,decrypt-cbc --in key.pub assert_success "Import RSA public wrap key" run rm keypair.pem key.pub assert_success "Remove keypairs" #Wrap and unwrap EC object with imported RSA wrap key run "${command_args[@]}" -p password -a get-rsa-wrapped --wrap-id "$import_keyid" -i "$eckey" -t asymmetric-key --out rsawrapped.object assert_success "Export wrapped EC object" run "${command_args[@]}" -p password -a delete-object -i "$eckey" -t asymmetric-key assert_success "Delete EC key" run "${command_args[@]}" -p password -a put-rsa-wrapped --wrap-id "$import_keyid" --in rsawrapped.object assert_success "Import wrapped EC objects" run "${command_args[@]}" -p password -a get-object-info -i "$eckey" -t asymmetric-key assert_success "Get object info" seq_ec=$((seq_ec+1)) assert_output --partial "sequence: "$seq_ec"" assert_output --partial "origin: imported:imported_wrapped" assert_output --partial "capabilities: exportable-under-wrap:sign-ecdsa" run "${command_args[@]}" -p password -a sign-ecdsa -i "$eckey" -A ecdsa-sha1 --in data.txt assert_success "Perform signature with imported wrapped EC key" run rm rsawrapped.object assert_success "Delete RSA wrapped object" #Wrap and unwrap EC key material with imported RSA wrap key run "${command_args[@]}" -p password -a get-rsa-wrapped-key --wrap-id "$import_keyid" -i "$eckey" -t asymmetric-key --oaep rsa-oaep-sha512 --mgf1 mgf1-sha512 --out rsawrapped.key assert_success "Export wrapped EC key material" run "${command_args[@]}" -p password -a delete-object -i "$eckey" -t asymmetric-key assert_success "Delete EC key" run "${command_args[@]}" -p password -a put-rsa-wrapped-key --wrap-id "$import_keyid" -i "$eckey" -t asymmetric-key -A ecp224 -c exportable-under-wrap,sign-ecdsa --oaep rsa-oaep-sha512 --mgf1 mgf1-sha512 --in rsawrapped.key assert_success "Import wrapped EC key material" run "${command_args[@]}" -p password -a get-object-info -i "$eckey" -t asymmetric-key assert_success "Get object info" seq_ec=$((seq_ec+1)) assert_output --partial "sequence: "$seq_ec"" assert_output --partial "origin: imported:imported_wrapped" assert_output --partial "capabilities: exportable-under-wrap:sign-ecdsa" run "${command_args[@]}" -p password -a sign-ecdsa -i "$eckey" -A ecdsa-sha1 --in data.txt assert_success "Perform signature with imported wrapped EC key" run rm rsawrapped.key assert_success "Removed RSA wrapped key" if [[ "$aes_enabled" = true ]]; then #Wrap and unwrap AES object with imported RSA wrap key run "${command_args[@]}" -p password -a get-rsa-wrapped --wrap-id "$import_keyid" -i "$aeskey" -t symmetric-key --out rsawrapped.object assert_success "Export wrapped AES object" run "${command_args[@]}" -p password -a delete-object -i "$aeskey" -t symmetric-key assert_success "Deleta AES key" run "${command_args[@]}" -p password -a put-rsa-wrapped --wrap-id "$import_keyid" --in rsawrapped.object assert_success "Import wrapped AES object" run "${command_args[@]}" -p password -a get-object-info -i "$aeskey" -t symmetric-key assert_success "Get object info" seq_aes=$((seq_aes+1)) assert_output --partial "sequence: "$seq_aes"" assert_output --partial "origin: imported:imported_wrapped" assert_output --partial "capabilities: decrypt-cbc:encrypt-cbc:exportable-under-wrap" run "${command_args[@]}" -p password -a encrypt-aescbc -i "$aeskey" --iv "$iv" --in "$data" --out data.enc assert_success "Perform encryption with imported wrapped AES key" run "${command_args[@]}" -p password -a decrypt-aescbc -i "$aeskey" --iv "$iv" --in data.enc assert_success "Perform decryption with imported wrapped AES key" run "${command_args[@]}" -p password -a decrypt-aescbc -i "$aeskey" --iv "$iv" --in data.enc assert_success "Decryption succeeded" last_line_of_output=$(echo "$output" | tail -n 1) assert_equal "$last_line_of_output" "$data" run rm rsawrapped.object data.enc assert_success "Removed RSA wrapped object and encrypted data" #Wrap and unwrap AES key material with imported RSA wrap key run "${command_args[@]}" -p password -a get-rsa-wrapped-key --wrap-id "$import_keyid" -i "$aeskey" -t symmetric-key --oaep rsa-oaep-sha1 --mgf1 mgf1-sha384 --out rsawrapped.key assert_success "Export wrapped AES key material" run "${command_args[@]}" -p password -a delete-object -i "$aeskey" -t symmetric-key assert_success "Delete AES key" run "${command_args[@]}" -p password -a put-rsa-wrapped-key --wrap-id "$import_keyid" -i "$aeskey" -t symmetric-key -A aes128 -c exportable-under-wrap,decrypt-cbc,encrypt-cbc --oaep rsa-oaep-sha1 --mgf1 mgf1-sha384 --in rsawrapped.key assert_success "Import wrapped AES key materiak" run "${command_args[@]}" -p password -a get-object-info -i "$aeskey" -t symmetric-key assert_success "Get object info" seq_aes=$((seq_aes+1)) assert_output --partial "sequence: "$seq_aes"" assert_output --partial "origin: imported:imported_wrapped" assert_output --partial "capabilities: decrypt-cbc:encrypt-cbc:exportable-under-wrap" run "${command_args[@]}" -p password -a sign-ecdsa -i "$eckey" -A ecdsa-sha1 --in data.txt assert_success "Perform encryption with imported wrapped EC key" run "${command_args[@]}" -p password -a encrypt-aescbc -i "$aeskey" --iv "$iv" --in "$data" --out data.enc assert_success "Perform encryption with imported wrapped AES key" run "${command_args[@]}" -p password -a decrypt-aescbc -i "$aeskey" --iv "$iv" --in data.enc assert_success "Perform decryption with imported wrapped AES key" run "${command_args[@]}" -p password -a decrypt-aescbc -i "$aeskey" --iv "$iv" --in data.enc assert_success "Decryption succeeded" last_line_of_output=$(echo "$output" | tail -n 1) assert_equal "$last_line_of_output" "$data" run rm rsawrapped.key data.enc assert_success "Removed RSA wrapped key and encrypted data" fi #Clean up run "${command_args[@]}" -p password -a delete-object -i "$keyid" -t wrap-key assert_success "Delete generated RSA wrap key" run "${command_args[@]}" -p password -a delete-object -i "$keyid" -t public-wrap-key assert_success "Delete generated RSA public wrap key" run "${command_args[@]}" -p password -a delete-object -i "$import_keyid" -t wrap-key assert_success "Delete imported RSA wrap key" run "${command_args[@]}" -p password -a delete-object -i "$import_keyid" -t public-wrap-key assert_success "Delete imported RSA public wrap key" done } @test "List Objects" { [[ "$LIST_TESTS" == "true" ]] || skip "skipping right now" command_args=("$BIN" "$c_var" "$SPECIFIED_CONNECTOR") run "${command_args[@]}" -p password -a reset assert_success "HSM was reset" sleep 3 run "${command_args[@]}" -p password -a generate-asymmetric-key -i 100 -l ecKey -d 5,8,13 -c sign-ecdsa,derive-ecdh,sign-attestation-certificate -A ecp224 assert_success "Generate EC key for testing" run "${command_args[@]}" -p password -a list-objects -A any -t any -i 100 assert_success "List objects by ID" assert_output --partial "Found 1 object(s)" run "${command_args[@]}" -p password -a list-objects -A any -t asymmetric-key assert_success "List objects by type" assert_output --partial "Found 1 object(s)" run "${command_args[@]}" -p password -a list-objects -A any -t any -d 5,8,13 assert_success "List objects by domain" assert_output --partial "Found 2 object(s)" run "${command_args[@]}" -p password -a list-objects -A any -t any -c sign-ecdsa,derive-ecdh,sign-attestation-certificate assert_success "List objects by capabilities" assert_output --partial "Found 2 object(s)" run "${command_args[@]}" -p password -a list-objects -A ecp224 -t any assert_success "List objects by algorithm" assert_output --partial "Found 1 object(s)" run "${command_args[@]}" -p password -a list-objects -A any -t any -l ecKey assert_success "List objects by label" assert_output --partial "Found 1 object(s)" run "${command_args[@]}" -p password -a delete-object -i 100 -t asymmetric-key assert_success "Delete key" } @test "Label Size" { [[ "$LABEL_TESTS" == "true" ]] || skip "skipping right now" command_args=("$BIN" "$c_var" "$SPECIFIED_CONNECTOR") run "${command_args[@]}" -p password -a reset assert_success "HSM was reset" sleep 3 run "${command_args[@]}" -p password -a generate-asymmetric-key -i 300 -d 5,8,13 -c sign-ecdsa -A ecp224 assert_success "Create key with no label" run "${command_args[@]}" -p password -a get-object-info -i 300 -t asymmetric-key assert_success "Get info for key with no label" assert_output --partial "label: \"\"" # --- Test with 39-character label --- run "${command_args[@]}" -p password -a generate-asymmetric-key -i 200 -l abcdefghijklmnopqrstuvwxyz0123456789abc -d 5,8,13 -c sign-ecdsa -A ecp224 assert_success "Create object with 39-character label" run "${command_args[@]}" -p password -a get-object-info -i 200 -t asymmetric-key assert_success "Get info for 39-character label" assert_output --partial "label: \"abcdefghijklmnopqrstuvwxyz0123456789abc\"" run "${command_args[@]}" -p password -a list-objects -A any -t any -l abcdefghijklmnopqrstuvwxyz0123456789abc assert_success "List objects with 39-character label" assert_output --partial "Found 1 object(s)" # --- Test with 40-character label --- run "${command_args[@]}" -p password -a generate-asymmetric-key -i 100 -l abcdefghijklmnopqrstuvwxyz0123456789abcd -d 5,8,13 -c sign-ecdsa -A ecp224 assert_success "Create object with 40-character label" run "${command_args[@]}" -p password -a list-objects -A any -t any -l abcdefghijklmnopqrstuvwxyz0123456789abcd assert_success "List objects with 40-character label" assert_output --partial "Found 1 object(s)" # --- Test that 41-character label FAILS --- run "${command_args[@]}" -p password -a generate-asymmetric-key -i 400 -l "abcdefghijklmnopqrstuvwxyz0123456789abcde" -d "5,8,13" -c "sign-ecdsa" -A "ecp224" assert_failure assert_output --partial "Invalid argument to a function" # --- Test listing a non-existent label --- run "${command_args[@]}" -p password -a list-objects -A any -t any -l doesnotexist assert_success "List objects by non-existent label" assert_output --partial "Found 0 object(s)" # --- Clean up created objects --- run "${command_args[@]}" -p password -a delete-object -i 100 -t asymmetric-key assert_success "Clean up key 100" run "${command_args[@]}" -p password -a delete-object -i 200 -t asymmetric-key assert_success "Clean up key 200" run "${command_args[@]}" -p password -a delete-object -i 300 -t asymmetric-key assert_success "Clean up key 300" } @test "Authentication" { [[ "$AUTHENTICATION_TESTS" == "true" ]] || skip "skipping right now" command_args=("$BIN" "$c_var" "$SPECIFIED_CONNECTOR") run "${command_args[@]}" -p password -a reset assert_success "HSM was reset" sleep 3 run "${command_args[@]}" -p password -a put-authentication-key -i 0 -l authkey -d 1,2,3 -c all --delegated all --new-password foo123 assert_success "Create new authentication key" keyid=$(echo "$output" | tail -1 | awk '{print $4}') run "${command_args[@]}" --authkey "$keyid" -p foo123 -a get-object-info -i 1 -t authentication-key assert_success "Authenticate with new authentication key" run "${command_args[@]}" -p password -a delete-object -i "$keyid" -t authentication-key assert_success "Delete authentication key" }yubihsm-shell-2.7.1/lib/0000755000175100017510000000000015133003406014455 5ustar runnerrunneryubihsm-shell-2.7.1/lib/yubihsm_libusb.c0000644000175100017510000001234315133003406017644 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "yubihsm.h" #include "internal.h" #include "yubihsm_usb.h" #include "debug_lib.h" #ifdef NO_LIBUSB_STRERROR #define libusb_strerror(x) libusb_error_name(x) #endif struct state { libusb_context *ctx; libusb_device_handle *handle; unsigned long serial; }; void usb_set_serial(yh_backend *state, unsigned long serial) { state->serial = serial; } void usb_close(yh_backend *state) { if (state && state->handle) { libusb_release_interface(state->handle, 0); libusb_close(state->handle); state->handle = NULL; } } void usb_destroy(yh_backend **state) { if (state && *state) { usb_close(*state); if ((*state)->ctx) { libusb_exit((*state)->ctx); (*state)->ctx = NULL; } free(*state); *state = NULL; } } yh_backend *backend_create(void) { DBG_INFO("backend_create"); yh_backend *backend = calloc(1, sizeof(yh_backend)); if (backend) { if (libusb_init(&backend->ctx) != 0) { free(backend); backend = NULL; } } return backend; } bool usb_open_device(yh_backend *backend) { libusb_device **list; libusb_device_handle *h = NULL; ssize_t cnt = libusb_get_device_list(backend->ctx, &list); if (backend->handle) { usb_close(backend); } if (cnt < 0) { DBG_ERR("Failed to get device list: %s", libusb_strerror(cnt)); return NULL; } for (ssize_t i = 0; i < cnt; i++) { struct libusb_device_descriptor desc; int ret = libusb_get_device_descriptor(list[i], &desc); if (ret != 0) { DBG_INFO("Failed to get descriptor for device %zd: %s", i, libusb_strerror(ret)); continue; } if (desc.idVendor == YH_VID && desc.idProduct == YH_PID) { ret = libusb_open(list[i], &h); if (ret != 0 || h == NULL) { DBG_INFO("Failed to open device for index %zd: %s", i, libusb_strerror(ret)); continue; } if (backend->serial != 0) { unsigned char data[16] = {0}; ret = libusb_get_string_descriptor_ascii(h, desc.iSerialNumber, data, sizeof(data)); unsigned long devSerial = strtoul((char *) data, NULL, 10); if (devSerial != backend->serial) { DBG_INFO("Device %zd has serial %lu, not matching searched %lu", i, devSerial, backend->serial); goto next; } } ret = libusb_claim_interface(h, 0); if (ret != 0) { DBG_ERR("Failed to claim interface: %s of device %zd", libusb_strerror(ret), i); goto next; } break; next: libusb_close(h); h = NULL; } } libusb_free_device_list(list, 1); backend->handle = h; if (h) { // we set up a dummy read with a 1ms timeout here. The reason for doing this // is that there might be data left in th e device buffers from earlier // transactions, this should flush it. unsigned char buf[YH_MSG_BUF_SIZE]; int transferred = 0; if (libusb_bulk_transfer(h, 0x81, buf, sizeof(buf), &transferred, 1) == 0) { DBG_INFO("%d bytes of stale data read from device", transferred); } return true; } else { return false; } } int usb_write(yh_backend *state, unsigned char *buf, long unsigned len) { int transferred = 0; if (state->handle == NULL) { DBG_ERR("Handle is not connected"); return 0; } /* TODO: does this need to loop and transmit several times? */ int ret = libusb_bulk_transfer(state->handle, 0x01, buf, len, &transferred, 0); DBG_INFO("Write of %lu %d, ret %d", len, transferred, ret); if (ret != 0) { DBG_ERR("Failed usb_write with ret: %d (%s)", ret, libusb_strerror(ret)); return 0; } else if (transferred != (int) len) { DBG_ERR("Transferred did not match len of write %d-%lu", transferred, len); return 0; } if (len % 64 == 0) { transferred = 0; /* this writes the ZLP */ ret = libusb_bulk_transfer(state->handle, 0x01, buf, 0, &transferred, 0); if (ret != 0) { DBG_ERR("Failed usb_write ZLP with ret: %d (%s)", ret, libusb_strerror(ret)); return 0; } } return 1; } int usb_read(yh_backend *state, unsigned char *buf, unsigned long *len) { int transferred = 0; int ret; if (state->handle == NULL) { DBG_ERR("Handle is not connected"); return 0; } DBG_INFO("Doing usb read"); /* TODO: does this need to loop for all data?*/ ret = libusb_bulk_transfer(state->handle, 0x81, buf, *len, &transferred, 0); if (ret != 0) { DBG_ERR("Failed usb_read with ret: %d (%s)", ret, libusb_strerror(ret)); return 0; } DBG_INFO("Read, transfer %d", transferred); *len = transferred; return 1; } yubihsm-shell-2.7.1/lib/yubihsm_winhttp.c0000644000175100017510000002305015133003406020056 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include #include "yubihsm.h" #include "internal.h" #include "debug_lib.h" #define MAX_STR_LEN 128 #define UNUSED(x) (void) (x) struct urlComponents { bool https; wchar_t hostname[MAX_STR_LEN + 1]; int port; wchar_t path[MAX_STR_LEN + 1]; }; struct state { HINTERNET session; HINTERNET connection; yh_connector *connector; struct urlComponents status_url; struct urlComponents api_url; }; uint8_t YH_INTERNAL _yh_verbosity; FILE YH_INTERNAL *_yh_output; static bool parseUrl(const char *url, struct urlComponents *components) { wchar_t wUrl[MAX_STR_LEN * 2]; size_t len = mbstowcs(wUrl, url, _countof(wUrl)); if (len == _countof(wUrl)) { return false; } URL_COMPONENTS c = {sizeof(c)}; c.lpszHostName = components->hostname; c.dwHostNameLength = _countof(components->hostname); c.lpszUrlPath = components->path; c.dwUrlPathLength = _countof(components->path); if (!WinHttpCrackUrl(wUrl, (DWORD) len, 0, &c)) { return false; } components->https = c.nScheme == INTERNET_SCHEME_HTTPS; components->port = c.nPort; return true; } static void backend_set_verbosity(uint8_t verbosity, FILE *output) { _yh_verbosity = verbosity; _yh_output = output; } static yh_rc backend_init(uint8_t verbosity, FILE *output) { DBG_INFO("backend_init"); backend_set_verbosity(verbosity, output); return YHR_SUCCESS; } static void backend_cleanup(void) { DBG_INFO("backend_cleanup"); } static yh_backend *backend_create(void) { DBG_INFO("backend_create"); yh_backend *backend = calloc(1, sizeof(yh_backend)); if (backend) { backend->session = WinHttpOpen(L"YubiHSM WinHttp/" VERSION, WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); } return backend; } static void backend_disconnect(yh_backend *connection) { DBG_INFO("backend_disconnect"); WinHttpCloseHandle(connection->connection); WinHttpCloseHandle(connection->session); free(connection); } static yh_rc backend_connect(yh_connector *connector, int timeout) { DBG_INFO("backend_connect"); if (timeout == 0) { // TODO: what does winhttp do if it gets timeout 0? timeout = 300; } yh_backend *backend = connector->connection; backend->connector = connector; if (!parseUrl(connector->status_url, &backend->status_url)) { DBG_ERR("Status URL parsing failed."); return YHR_INVALID_PARAMETERS; } if (!parseUrl(connector->api_url, &backend->api_url)) { DBG_ERR("Api URL parsing failed."); return YHR_INVALID_PARAMETERS; } DBG_INFO("Connecting to %s", connector->status_url); backend->connection = WinHttpConnect(backend->session, backend->status_url.hostname, backend->status_url.port, 0); if (!backend->connection) { DBG_ERR("Failed connecting to %s", connector->status_url); return YHR_CONNECTOR_ERROR; } HINTERNET request = WinHttpOpenRequest(backend->connection, L"GET", backend->status_url.path, NULL, NULL, WINHTTP_DEFAULT_ACCEPT_TYPES, backend->status_url.https ? WINHTTP_FLAG_SECURE : 0); if (!request) { DBG_ERR("Failed opening request to %s", connector->status_url); return YHR_CONNECTOR_ERROR; } if (timeout > 0) { if (!WinHttpSetTimeouts(request, timeout * 1000, timeout * 1000, timeout * 1000, timeout * 1000)) { DBG_ERR("Failed setting timeouts."); } } DBG_INFO("Sending request to %s", connector->status_url); if (!WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0)) { DBG_ERR("Failed sending request to %s", connector->status_url); WinHttpCloseHandle(request); return YHR_CONNECTOR_ERROR; } if (!WinHttpReceiveResponse(request, 0)) { DBG_ERR("Failed receiving response from %s", connector->status_url); WinHttpCloseHandle(request); return YHR_CONNECTOR_ERROR; } DWORD dwStatusCode, dwSize = sizeof(dwStatusCode); if (!WinHttpQueryHeaders(request, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &dwStatusCode, &dwSize, WINHTTP_NO_HEADER_INDEX)) { DBG_ERR("Failed retrieveing status code from %s", backend->connector->status_url); WinHttpCloseHandle(request); return YHR_CONNECTOR_ERROR; } if (dwStatusCode != 200) { DBG_ERR("Invalid status code %u received from %s", dwStatusCode, backend->connector->status_url); WinHttpCloseHandle(request); return YHR_CONNECTOR_ERROR; } char buf[256]; DWORD offs = 0, bytes; while (WinHttpReadData(request, buf + offs, sizeof(buf) - offs, &bytes)) { if (bytes == 0) break; offs += bytes; if (offs >= sizeof(buf)) break; } DBG_INFO("Read %u bytes from %s", offs, connector->status_url); WinHttpCloseHandle(request); parse_status_data(buf, connector); if (!connector->has_device) { DBG_ERR("Response from %s indicates no device is present", connector->status_url); return YHR_CONNECTOR_NOT_FOUND; } return YHR_SUCCESS; } static yh_rc backend_send_msg(yh_backend *backend, Msg *msg, Msg *response, const char *identifier) { uint16_t raw_len = ntohs(msg->st.len) + 3; wchar_t hsm_identifier[64]; wchar_t *headers = WINHTTP_NO_ADDITIONAL_HEADERS; DWORD headers_len = 0; if (identifier != NULL && strlen(identifier) > 0 && strlen(identifier) < 32) { headers_len = swprintf(hsm_identifier, 64, L"YubiHSM-Session: %hs", identifier); headers = hsm_identifier; } HINTERNET request = WinHttpOpenRequest(backend->connection, L"POST", backend->api_url.path, NULL, NULL, WINHTTP_DEFAULT_ACCEPT_TYPES, backend->api_url.https ? WINHTTP_FLAG_SECURE : 0); if (!request) { DBG_ERR("Failed opening request to %s", backend->connector->api_url); return YHR_CONNECTOR_ERROR; } // TODO: replace these magic numbers with something better. // of note here is the 250s timeout on receive, generating rsa4096 might take // some time.. if (!WinHttpSetTimeouts(request, 30 * 1000, 30 * 1000, 250 * 1000, 250 * 1000)) { DBG_ERR("Failed setting timeouts."); } DBG_INFO("Sending %u bytes to %s", raw_len, backend->connector->api_url); if (!WinHttpSendRequest(request, headers, headers_len, msg->raw, raw_len, raw_len, 0)) { DBG_ERR("Failed sending request to %s", backend->connector->api_url); WinHttpCloseHandle(request); return YHR_CONNECTOR_ERROR; } if (!WinHttpReceiveResponse(request, 0)) { DBG_ERR("Failed receiving response from %s", backend->connector->api_url); WinHttpCloseHandle(request); return YHR_CONNECTOR_ERROR; } DWORD dwStatusCode, dwSize = sizeof(dwStatusCode); if (!WinHttpQueryHeaders(request, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &dwStatusCode, &dwSize, WINHTTP_NO_HEADER_INDEX)) { DBG_ERR("Failed retrieveing status code from %s", backend->connector->api_url); WinHttpCloseHandle(request); return YHR_CONNECTOR_ERROR; } if (dwStatusCode != 200) { DBG_ERR("Invalid status code %u received from %s", dwStatusCode, backend->connector->api_url); WinHttpCloseHandle(request); return YHR_CONNECTOR_ERROR; } DWORD offs = 0, bytes; while (WinHttpReadData(request, response->raw + offs, sizeof(response->raw) - offs, &bytes)) { if (bytes == 0) break; offs += bytes; if (offs >= sizeof(response->raw)) break; } DBG_INFO("Read %u bytes from %s", offs, backend->connector->api_url); WinHttpCloseHandle(request); if (offs < 3) { DBG_ERR("Not enough data received; %lu", offs); return YHR_WRONG_LENGTH; } if (ntohs(response->st.len) != offs - 3) { DBG_ERR("Wrong length received, %d vs %lu", ntohs(response->st.len), offs); return YHR_WRONG_LENGTH; } return YHR_SUCCESS; } static yh_rc backend_option(yh_backend *connection, yh_connector_option opt, const void *val) { UNUSED(connection); UNUSED(opt); UNUSED(val); DBG_ERR("Backend options not (yet?) supported with winhttp"); return YHR_CONNECTOR_ERROR; } static struct backend_functions f = {backend_init, backend_create, backend_connect, backend_disconnect, backend_send_msg, backend_cleanup, backend_option, backend_set_verbosity}; #ifdef STATIC struct backend_functions *http_backend_functions(void) { #else struct backend_functions *backend_functions(void) { #endif return &f; } yubihsm-shell-2.7.1/lib/debug_lib.h0000644000175100017510000001033715133003406016546 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef DEBUG_LIB_H #define DEBUG_LIB_H #ifdef _MSVC #include #include #else #include #endif #include #include #include "yubihsm.h" #include "../common/debug.h" extern uint8_t _yh_verbosity; extern FILE *_yh_output; #define DUMPIF(var, len, lev) \ do { \ if (_yh_verbosity & lev) { \ dump_hex(_yh_output, var, len); \ fprintf(_yh_output, "\n"); \ } \ } while (0) #define DBG_INT(var, len, ...) \ do { \ D(_yh_verbosity &YH_VERB_INTERMEDIATE, _yh_output, ANSI_YELLOW, "LIB", \ "INT", __VA_ARGS__); \ DUMPIF(var, len, YH_VERB_INTERMEDIATE); \ } while (0) #define DBG_CRYPTO(var, len, ...) \ do { \ D(_yh_verbosity &YH_VERB_CRYPTO, _yh_output, ANSI_GREEN, "LIB", "CRY", \ __VA_ARGS__); \ DUMPIF(var, len, YH_VERB_CRYPTO); \ } while (0) #define DBG_NET(var, dump) \ do { \ D(_yh_verbosity &YH_VERB_RAW, _yh_output, ANSI_MAGENTA, "LIB", "NET", \ " "); \ if (_yh_verbosity & YH_VERB_RAW) { \ dump(_yh_output, (var)); \ } \ } while (0) #define DBG_INFO(...) \ do { \ DLN(_yh_verbosity &YH_VERB_INFO, _yh_output, ANSI_BLUE, "LIB", "INF", \ __VA_ARGS__); \ } while (0) #define DBG_DUMPINFO(var, len, ...) \ do { \ D(_yh_verbosity &YH_VERB_INFO, _yh_output, ANSI_BLUE, "LIB", "INF", \ __VA_ARGS__); \ DUMPIF(var, len, YH_VERB_INFO); \ } while (0) #define DBG_ERR(...) \ do { \ DLN(_yh_verbosity &YH_VERB_ERR, _yh_output, ANSI_RED, "LIB", "ERR", \ __VA_ARGS__); \ } while (0) #endif #define DBG_DUMPERR(var, len, ...) \ do { \ D(_yh_verbosity &YH_VERB_ERR, _yh_output, ANSI_RED, "LIB", "ERR", \ __VA_ARGS__); \ DUMPIF(var, len, YH_VERB_ERR); \ } while (0) yubihsm-shell-2.7.1/lib/yubihsm.h0000644000175100017510000036000115133003406016306 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** @mainpage @section Introduction Libyubihsm is a library for communicating with a YubiHSM 2 device. @section Usage To use the library, include in the C code and pass the -lyubihsm flag to the linker. Debug output is controlled with the function #yh_set_verbosity(). First step of using a YubiHSM 2 is to initialize the library with #yh_init(), initialize a connector with #yh_init_connector() and then connect it to the YubiHSM 2 with #yh_connect(). After this, a session must be established with #yh_create_session_derived(), #yh_create_session(), #yh_begin_create_session() + yh_finish_create_session(). When a session is established, commands can be exchanged over it. The functions in the namespace yh_util are high-level convenience functions that do specific tasks with the device. @section api API Reference All public functions and definitions can be found in yubihsm.h @section example Code example Here is a small example of establishing a session with a YubiHSM 2 and fetching some pseudo random bytes before closing the session. \code{.c} int main(void) { yh_connector *connector = NULL; yh_session *session = NULL; uint8_t data[128] = {0}; size_t data_len = sizeof(data); assert(yh_init() == YHR_SUCCESS); assert(yh_init_connector("http://localhost:12345", &connector)==YHR_SUCCESS); assert(yh_connect(connector, 0) == YHR_SUCCESS); assert(yh_create_session_derived(connector, 1, YH_DEFAULT_PASSWORD, strlen(YH_DEFAULT_PASSWORD), false, &session) == YHR_SUCCESS); assert(yh_util_get_pseudo_random(session, sizeof(data), data, &data_len)==YHR_SUCCESS); assert(data_len == sizeof(data)); assert(yh_util_close_session(session) == YHR_SUCCESS); assert(yh_destroy_session(&session) == YHR_SUCCESS); assert(yh_disconnect(connector) == YHR_SUCCESS); } \endcode */ /** @file yubihsm.h * * Everything you need to establish a connection to the YubiHSM 2 and use its * functions. */ #ifndef YUBIHSM_H #define YUBIHSM_H #include #include #include #include /// Length of context array for authentication #define YH_CONTEXT_LEN 16 /// Length of host challenge for authentication #define YH_HOST_CHAL_LEN 8 /// Maximum length of message buffer #ifndef FUZZING #define YH_MSG_BUF_SIZE 3136 #else // in fuzzing builds make the data buffers smaller #define YH_MSG_BUF_SIZE 100 #endif /// Length of authentication keys #define YH_KEY_LEN 16 /// Device vendor ID #define YH_VID 0x1050 /// Device product ID #define YH_PID 0x0030 /// Response flag for commands #define YH_CMD_RESP_FLAG 0x80 /// Max items the device may hold #define YH_MAX_ITEMS_COUNT 256 /// Max sessions the device may hold #define YH_MAX_SESSIONS 16 /// Default encryption key #define YH_DEFAULT_ENC_KEY \ "\x09\x0b\x47\xdb\xed\x59\x56\x54\x90\x1d\xee\x1c\xc6\x55\xe4\x20" /// Default MAC key #define YH_DEFAULT_MAC_KEY \ "\x59\x2f\xd4\x83\xf7\x59\xe2\x99\x09\xa0\x4c\x45\x05\xd2\xce\x0a" /// Default authentication key password #define YH_DEFAULT_PASSWORD "password" /// Salt to be used for PBKDF2 key derivation #define YH_DEFAULT_SALT "Yubico" /// Number of iterations for PBKDF2 key derivation #define YH_DEFAULT_ITERS 10000 /// Length of capabilities array #define YH_CAPABILITIES_LEN 8 /// Max log entries the device may hold #define YH_MAX_LOG_ENTRIES 64 /// Max length of object labels #define YH_OBJ_LABEL_LEN 40 /// Max number of domains #define YH_MAX_DOMAINS 16 /// Size that the log digest is truncated to #define YH_LOG_DIGEST_SIZE 16 /// URL scheme used for direct USB access #define YH_USB_URL_SCHEME "yhusb://" /// URL scheme used for fuzzing builds #define YH_FUZZ_URL_SCHEME "yhfuzz://" // Debug levels /// Debug level quiet. No messages printed out #define YH_VERB_QUIET 0x00 /// Debug level intermediate. Intermediate results printed out #define YH_VERB_INTERMEDIATE 0x01 /// Debug level crypto. Crypto results printed out #define YH_VERB_CRYPTO 0x02 /// Debug level raw. Raw messages printed out #define YH_VERB_RAW 0x04 /// Debug level info. General information messages printed out #define YH_VERB_INFO 0x08 /// Debug level error. Error messages printed out #define YH_VERB_ERR 0x10 /// Debug level all. All previous options enabled #define YH_VERB_ALL 0xff /// This is the overhead when doing aes-ccm wrapping: 1 byte identifier, 13 /// bytes nonce and 16 bytes mac #define YH_CCM_WRAP_OVERHEAD (1 + 13 + 16) #define YH_EC_P256_PRIVKEY_LEN 32 #define YH_EC_P256_PUBKEY_LEN 65 #ifdef __cplusplus extern "C" { #endif /// Reference to a connector typedef struct yh_connector yh_connector; /// Reference to a session typedef struct yh_session yh_session; /// Capabilities representation typedef struct { /// Capabilities is represented as an 8 byte uint8_t array uint8_t capabilities[YH_CAPABILITIES_LEN]; } yh_capabilities; /** * Return codes. **/ typedef enum { /// Returned value when function was successful YHR_SUCCESS = 0, /// Returned value when unable to allocate memory YHR_MEMORY_ERROR = -1, /// Returned value when failing to initialize libyubihsm YHR_INIT_ERROR = -2, /// Returned value when a connection error was encountered YHR_CONNECTION_ERROR = -3, /// Returned value when failing to find a suitable connector YHR_CONNECTOR_NOT_FOUND = -4, /// Returned value when an argument to a function is invalid YHR_INVALID_PARAMETERS = -5, /// Returned value when there is a mismatch between expected and received /// length of an argument to a function YHR_WRONG_LENGTH = -6, /// Returned value when there is not enough space to store data YHR_BUFFER_TOO_SMALL = -7, /// Returned value when failing to verify cryptogram YHR_CRYPTOGRAM_MISMATCH = -8, /// Returned value when failing to authenticate the session YHR_SESSION_AUTHENTICATION_FAILED = -9, /// Returned value when failing to verify MAC YHR_MAC_MISMATCH = -10, /// Returned value when the device returned no error YHR_DEVICE_OK = -11, /// Returned value when the device receives and invalid command YHR_DEVICE_INVALID_COMMAND = -12, /// Returned value when the device receives a malformed command invalid data YHR_DEVICE_INVALID_DATA = -13, /// Returned value when the device session is invalid YHR_DEVICE_INVALID_SESSION = -14, /// Return value when the device fails to encrypt or verify the message YHR_DEVICE_AUTHENTICATION_FAILED = -15, /// Return value when no more sessions can be opened on the device YHR_DEVICE_SESSIONS_FULL = -16, /// Return value when failing to create a device session YHR_DEVICE_SESSION_FAILED = -17, /// Return value when encountering a storage failure on the device YHR_DEVICE_STORAGE_FAILED = -18, /// Return value when there is a mismatch between expected and received /// length of an argument to a function on the device YHR_DEVICE_WRONG_LENGTH = -19, /// Return value when the permissions to perform the operation are wrong YHR_DEVICE_INSUFFICIENT_PERMISSIONS = -20, /// Return value when the log buffer is full and forced audit is set YHR_DEVICE_LOG_FULL = -21, /// Return value when the object not found on the device YHR_DEVICE_OBJECT_NOT_FOUND = -22, /// Return value when an invalid Object ID is used YHR_DEVICE_INVALID_ID = -23, /// Return value when an invalid OTP is submitted YHR_DEVICE_INVALID_OTP = -24, /// Return value when the device is in demo mode and has to be power cycled YHR_DEVICE_DEMO_MODE = -25, /// Return value when the command execution has not terminated YHR_DEVICE_COMMAND_UNEXECUTED = -26, /// Return value when encountering an unknown error YHR_GENERIC_ERROR = -27, /// Return value when trying to add an object with an ID that already exists YHR_DEVICE_OBJECT_EXISTS = -28, /// Return value when connector operation failed YHR_CONNECTOR_ERROR = -29, /// Return value when encountering SSH CA constraint violation YHR_DEVICE_SSH_CA_CONSTRAINT_VIOLATION = -30, /// Return value when an algorithm is disabled YHR_DEVICE_ALGORITHM_DISABLED = -31, } yh_rc; /// Macro to define command and response command #define ADD_COMMAND(c, v) c = v, c##_R = v | YH_CMD_RESP_FLAG /** * Command definitions */ typedef enum { /// Echo data back from the device. ADD_COMMAND(YHC_ECHO, 0x01), /// Create a session with the device. ADD_COMMAND(YHC_CREATE_SESSION, 0x03), /// Authenticate the session to the device ADD_COMMAND(YHC_AUTHENTICATE_SESSION, 0x04), /// Send a command over an established session ADD_COMMAND(YHC_SESSION_MESSAGE, 0x05), /// Get device metadata ADD_COMMAND(YHC_GET_DEVICE_INFO, 0x06), /// Factory reset a device ADD_COMMAND(YHC_RESET_DEVICE, 0x08), /// Get the device pubkey for asym auth ADD_COMMAND(YHC_GET_DEVICE_PUBKEY, 0x0a), /// Close session ADD_COMMAND(YHC_CLOSE_SESSION, 0x40), /// Get storage information ADD_COMMAND(YHC_GET_STORAGE_INFO, 0x041), /// Import an Opaque Object into the device ADD_COMMAND(YHC_PUT_OPAQUE, 0x42), /// Get an Opaque Object from device ADD_COMMAND(YHC_GET_OPAQUE, 0x43), /// Import an Authentication Key into the device ADD_COMMAND(YHC_PUT_AUTHENTICATION_KEY, 0x44), /// Import an Asymmetric Key into the device ADD_COMMAND(YHC_PUT_ASYMMETRIC_KEY, 0x45), /// Generate an Asymmetric Key in the device ADD_COMMAND(YHC_GENERATE_ASYMMETRIC_KEY, 0x46), /// Sign data using RSA-PKCS#1v1.5 ADD_COMMAND(YHC_SIGN_PKCS1, 0x47), /// List objects in the device ADD_COMMAND(YHC_LIST_OBJECTS, 0x48), /// Decrypt data that was encrypted using RSA-PKCS#1v1.5 ADD_COMMAND(YHC_DECRYPT_PKCS1, 0x49), /// Get an Object under wrap from the device. ADD_COMMAND(YHC_EXPORT_WRAPPED, 0x4a), /// Import a wrapped Object into the device ADD_COMMAND(YHC_IMPORT_WRAPPED, 0x4b), /// Import a Wrap Key into the device ADD_COMMAND(YHC_PUT_WRAP_KEY, 0x4c), /// Get all current audit log entries from the device Log Store ADD_COMMAND(YHC_GET_LOG_ENTRIES, 0x4d), /// Get all metadata about an Object ADD_COMMAND(YHC_GET_OBJECT_INFO, 0x4e), /// Set a device-global options that affect general behavior ADD_COMMAND(YHC_SET_OPTION, 0x4f), /// Get a device-global option ADD_COMMAND(YHC_GET_OPTION, 0x50), /// Get a fixed number of pseudo-random bytes from the device ADD_COMMAND(YHC_GET_PSEUDO_RANDOM, 0x51), /// Import a HMAC key into the device ADD_COMMAND(YHC_PUT_HMAC_KEY, 0x52), /// Perform an HMAC operation in the device ADD_COMMAND(YHC_SIGN_HMAC, 0x53), /// Get the public key of an Asymmetric Key in the device ADD_COMMAND(YHC_GET_PUBLIC_KEY, 0x54), /// Sign data using RSA-PSS ADD_COMMAND(YHC_SIGN_PSS, 0x55), /// Sign data using ECDSA ADD_COMMAND(YHC_SIGN_ECDSA, 0x56), /// Perform an ECDH key exchange operation with a private key in the device ADD_COMMAND(YHC_DERIVE_ECDH, 0x57), /// Delete object in the device ADD_COMMAND(YHC_DELETE_OBJECT, 0x58), /// Decrypt data using RSA-OAEP ADD_COMMAND(YHC_DECRYPT_OAEP, 0x59), /// Generate an HMAC Key in the device ADD_COMMAND(YHC_GENERATE_HMAC_KEY, 0x5a), /// Generate a Wrap Key in the device ADD_COMMAND(YHC_GENERATE_WRAP_KEY, 0x5b), /// Verify a generated HMAC ADD_COMMAND(YHC_VERIFY_HMAC, 0x5c), /// Sign SSH certificate request ADD_COMMAND(YHC_SIGN_SSH_CERTIFICATE, 0x5d), /// Import a template into the device ADD_COMMAND(YHC_PUT_TEMPLATE, 0x5e), /// Get a template from the device ADD_COMMAND(YHC_GET_TEMPLATE, 0x5f), /// Decrypt a Yubico OTP ADD_COMMAND(YHC_DECRYPT_OTP, 0x60), /// Create a Yubico OTP AEAD ADD_COMMAND(YHC_CREATE_OTP_AEAD, 0x61), /// Generate an OTP AEAD from random data ADD_COMMAND(YHC_RANDOMIZE_OTP_AEAD, 0x62), /// Re-encrypt a Yubico OTP AEAD from one OTP AEAD Key to another OTP AEAD Key ADD_COMMAND(YHC_REWRAP_OTP_AEAD, 0x63), /// Get attestation of an Asymmetric Key ADD_COMMAND(YHC_SIGN_ATTESTATION_CERTIFICATE, 0x64), /// Import an OTP AEAD Key into the device ADD_COMMAND(YHC_PUT_OTP_AEAD_KEY, 0x65), /// Generate an OTP AEAD Key in the device ADD_COMMAND(YHC_GENERATE_OTP_AEAD_KEY, 0x66), /// Set the last extracted audit log entry ADD_COMMAND(YHC_SET_LOG_INDEX, 0x67), /// Encrypt (wrap) data using a Wrap Key ADD_COMMAND(YHC_WRAP_DATA, 0x68), /// Decrypt (unwrap) data using a Wrap Key ADD_COMMAND(YHC_UNWRAP_DATA, 0x69), /// Sign data using EdDSA ADD_COMMAND(YHC_SIGN_EDDSA, 0x6a), /// Blink the LED of the device ADD_COMMAND(YHC_BLINK_DEVICE, 0x6b), /// Replace the Authentication Key used to establish the current Session. ADD_COMMAND(YHC_CHANGE_AUTHENTICATION_KEY, 0x6c), /// Import a Symmetric Key into the device ADD_COMMAND(YHC_PUT_SYMMETRIC_KEY, 0x6d), /// Generate a Symmetric Key in the device ADD_COMMAND(YHC_GENERATE_SYMMETRIC_KEY, 0x6e), /// Decrypt data using a Symmetric Key with ECB ADD_COMMAND(YHC_DECRYPT_ECB, 0x6f), /// Encrypt data using a Symmetric Key with ECB ADD_COMMAND(YHC_ENCRYPT_ECB, 0x70), /// Decrypt data using a Symmetric Key with CBC ADD_COMMAND(YHC_DECRYPT_CBC, 0x71), /// Encrypt data using a Symmetric Key with CBC ADD_COMMAND(YHC_ENCRYPT_CBC, 0x72), /// Import public RSA key as a Public Wrap Key ADD_COMMAND(YHC_PUT_PUBLIC_WRAPKEY, 0x73), /// Export (a)symmetric key using a Public Wrap Key ADD_COMMAND(YHC_GET_RSA_WRAPPED_KEY, 0x74), /// Import (a)symmetric key after unwrapping in using and RSA wrap key ADD_COMMAND(YHC_PUT_RSA_WRAPPED_KEY, 0x75), /// Wrap an object using an RSA Wrap Key ADD_COMMAND(YHC_EXPORT_RSA_WRAPPED, 0x76), /// Import an object after unwrapping in using and RSA Wrap Key ADD_COMMAND(YHC_IMPORT_RSA_WRAPPED, 0x77), /// The response byte returned from the device if the command resulted in an /// error YHC_ERROR = 0x7f, } yh_cmd; #undef ADD_COMMAND /** * Object types * * @see Objects */ typedef enum { /// Opaque Object is an unchecked kind of Object, normally used to store /// raw data in the device YH_OPAQUE = 0x01, /// Authentication Key is used to establish Sessions with a device YH_AUTHENTICATION_KEY = 0x02, /// Asymmetric Key is the private key of an asymmetric key-pair YH_ASYMMETRIC_KEY = 0x03, /// Wrap Key is a secret key used to wrap and unwrap Objects during the /// export and import process YH_WRAP_KEY = 0x04, /// HMAC Key is a secret key used when computing and verifying HMAC signatures YH_HMAC_KEY = 0x05, /// Template is a binary object used for example to validate SSH certificate /// requests YH_TEMPLATE = 0x06, /// OTP AEAD Key is a secret key used to decrypt Yubico OTP values YH_OTP_AEAD_KEY = 0x07, /// Symmetric Key is a secret key used for encryption and decryption. YH_SYMMETRIC_KEY = 0x08, /// Public Wrap Key is a public key used to wrap Objects during the /// export process YH_PUBLIC_WRAP_KEY = 0x09, /// Public Key is the public key of an asymmetric key-pair. The public key /// never exists in device and is mostly here for PKCS#11. YH_PUBLIC_KEY = 0x83, } yh_object_type; /// Max number of algorithms defined here #define YH_MAX_ALGORITHM_COUNT 0xff /** * Algorithms * * @see Objects */ typedef enum { /// rsa-pkcs1-sha1 YH_ALGO_RSA_PKCS1_SHA1 = 1, /// rsa-pkcs1-sha256 YH_ALGO_RSA_PKCS1_SHA256 = 2, /// rsa-pkcs1-sha384 YH_ALGO_RSA_PKCS1_SHA384 = 3, /// rsa-pkcs1-sha512 YH_ALGO_RSA_PKCS1_SHA512 = 4, /// rsa-pss-sha1 YH_ALGO_RSA_PSS_SHA1 = 5, /// rsa-pss-sha256 YH_ALGO_RSA_PSS_SHA256 = 6, /// rsa-pss-sha384 YH_ALGO_RSA_PSS_SHA384 = 7, /// rsa-pss-sha512 YH_ALGO_RSA_PSS_SHA512 = 8, /// rsa2048 YH_ALGO_RSA_2048 = 9, /// rsa3072 YH_ALGO_RSA_3072 = 10, /// rsa4096 YH_ALGO_RSA_4096 = 11, /// ecp256 YH_ALGO_EC_P256 = 12, /// ecp384 YH_ALGO_EC_P384 = 13, /// ecp521 YH_ALGO_EC_P521 = 14, /// eck256 YH_ALGO_EC_K256 = 15, /// ecbp256 YH_ALGO_EC_BP256 = 16, /// ecbp384 YH_ALGO_EC_BP384 = 17, /// ecbp512 YH_ALGO_EC_BP512 = 18, /// hmac-sha1 YH_ALGO_HMAC_SHA1 = 19, /// hmac-sha256 YH_ALGO_HMAC_SHA256 = 20, /// hmac-sha384 YH_ALGO_HMAC_SHA384 = 21, /// hmac-sha512 YH_ALGO_HMAC_SHA512 = 22, /// ecdsa-sha1 YH_ALGO_EC_ECDSA_SHA1 = 23, /// ecdh YH_ALGO_EC_ECDH = 24, /// rsa-oaep-sha1 YH_ALGO_RSA_OAEP_SHA1 = 25, /// rsa-oaep-sha256 YH_ALGO_RSA_OAEP_SHA256 = 26, /// rsa-oaep-sha384 YH_ALGO_RSA_OAEP_SHA384 = 27, /// rsa-oaep-sha512 YH_ALGO_RSA_OAEP_SHA512 = 28, /// aes128-ccm-wrap YH_ALGO_AES128_CCM_WRAP = 29, /// opaque-data YH_ALGO_OPAQUE_DATA = 30, /// opaque-x509-certificate YH_ALGO_OPAQUE_X509_CERTIFICATE = 31, /// mgf1-sha1 YH_ALGO_MGF1_SHA1 = 32, /// mgf1-sha256 YH_ALGO_MGF1_SHA256 = 33, /// mgf1-sha384 YH_ALGO_MGF1_SHA384 = 34, /// mgf1-sha512 YH_ALGO_MGF1_SHA512 = 35, /// template-ssh YH_ALGO_TEMPLATE_SSH = 36, /// aes128-yubico-otp YH_ALGO_AES128_YUBICO_OTP = 37, /// aes128-yubico-authentication YH_ALGO_AES128_YUBICO_AUTHENTICATION = 38, /// aes192-yubico-otp YH_ALGO_AES192_YUBICO_OTP = 39, /// aes256-yubico-otp YH_ALGO_AES256_YUBICO_OTP = 40, /// aes192-ccm-wrap YH_ALGO_AES192_CCM_WRAP = 41, /// aes256-ccm-wrap YH_ALGO_AES256_CCM_WRAP = 42, /// ecdsa-sha256 YH_ALGO_EC_ECDSA_SHA256 = 43, /// ecdsa-sha384 YH_ALGO_EC_ECDSA_SHA384 = 44, /// ecdsa-sha512 YH_ALGO_EC_ECDSA_SHA512 = 45, /// ed25519 YH_ALGO_EC_ED25519 = 46, /// ecp224 YH_ALGO_EC_P224 = 47, /// rsa-pkcs1-decrypt YH_ALGO_RSA_PKCS1_DECRYPT = 48, /// ec-p256-yubico-authentication YH_ALGO_EC_P256_YUBICO_AUTHENTICATION = 49, /// aes128 YH_ALGO_AES128 = 50, /// aes192 YH_ALGO_AES192 = 51, /// aes256 YH_ALGO_AES256 = 52, /// aes-ecb YH_ALGO_AES_ECB = 53, /// aes-cbc YH_ALGO_AES_CBC = 54, /// aes-kwp YH_ALGO_AES_KWP = 55, } yh_algorithm; /** * Global options */ typedef enum { /// Enable/Disable Forced Audit mode YH_OPTION_FORCE_AUDIT = 1, /// Enable/Disable logging of specific commands YH_OPTION_COMMAND_AUDIT = 3, /// Toggle algorithms on/off YH_OPTION_ALGORITHM_TOGGLE = 4, /// Fips mode on/off YH_OPTION_FIPS_MODE = 5, } yh_option; /** * Options for the connector, set with yh_set_connector_option() */ typedef enum { /// File with CA certificate to validate the connector with (const char *). /// Not implemented on Windows YH_CONNECTOR_HTTPS_CA = 1, /// Proxy server to use for connecting to the connector (const char *). Not /// implemented on Windows YH_CONNECTOR_PROXY_SERVER = 2, /// File with client certificate to authenticate client with (const char *). /// Not implemented on Windows YH_CONNECTOR_HTTPS_CERT = 3, /// File with client certificates key (const char *). /// Not implemented on Windows YH_CONNECTOR_HTTPS_KEY = 4, /// Comma separated list of hosts ignoring proxy, `*` to disable proxy. /// Not implemented on Windows YH_CONNECTOR_NOPROXY = 5, } yh_connector_option; /** * Options for data compression */ typedef enum { /// Do not compress data before importing it NO_COMPRESS = 1, /// Compress data if it's too big COMPRESS_IF_TOO_BIG = 2, /// Compress data before importing it COMPRESS = 3, } yh_compress_option; /** * Device info struct */ typedef struct { /// Firmware version major uint8_t major; /// Firmware version minor uint8_t minor; /// Firmware version patch uint8_t patch; /// Device serial number uint32_t serial; /// Total available logs uint8_t log_total; /// Total used logs uint8_t log_used; /// List of algorithms supported by the device yh_algorithm algorithms[YH_MAX_ALGORITHM_COUNT]; /// Number of algorithms supported by the device size_t n_algorithms; } yh_device_info; #pragma pack(push, 1) /** * Logging struct as returned by device * * @see Objects */ typedef struct { /// Monotonically increasing index uint16_t number; /// What command was executed @see yh_cmd uint8_t command; /// Length of in-data uint16_t length; /// ID of Authentication Key used uint16_t session_key; /// ID of first Object used uint16_t target_key; /// ID of second Object used uint16_t second_key; /// Command result @see yh_cmd uint8_t result; /// Systick at time of execution uint32_t systick; /// Truncated sha256 digest of this last digest + this entry uint8_t digest[YH_LOG_DIGEST_SIZE]; } yh_log_entry; /** * Object descriptor */ typedef struct { /// Object capabilities @see yh_capabilities yh_capabilities capabilities; /// Object ID uint16_t id; /// Object length uint16_t len; /// Object domains uint16_t domains; /// Object type yh_object_type type; /// Object algorithm yh_algorithm algorithm; /// Object sequence uint8_t sequence; /// Object origin uint8_t origin; /// Object label. The label consists of raw bytes and is not restricted to /// printable characters or valid UTF-8 glyphs char label[YH_OBJ_LABEL_LEN + 1]; /// Object delegated capabilities yh_capabilities delegated_capabilities; } yh_object_descriptor; #pragma pack(pop) static const struct { const char *name; int bit; } yh_capability[] = { {"change-authentication-key", 0x2e}, {"create-otp-aead", 0x1e}, {"decrypt-cbc", 0x34}, {"decrypt-ecb", 0x32}, {"decrypt-oaep", 0x0a}, {"decrypt-otp", 0x1d}, {"decrypt-pkcs", 0x09}, {"delete-asymmetric-key", 0x29}, {"delete-authentication-key", 0x28}, {"delete-hmac-key", 0x2b}, {"delete-opaque", 0x27}, {"delete-otp-aead-key", 0x2d}, {"delete-public-wrap-key", 0x55}, {"delete-symmetric-key", 0x31}, {"delete-template", 0x2c}, {"delete-wrap-key", 0x2a}, {"derive-ecdh", 0x0b}, {"encrypt-cbc", 0x35}, {"encrypt-ecb", 0x33}, {"export-wrapped", 0x0c}, {"exportable-under-wrap", 0x10}, {"generate-asymmetric-key", 0x04}, {"generate-hmac-key", 0x15}, {"generate-otp-aead-key", 0x24}, {"generate-symmetric-key", 0x30}, {"generate-wrap-key", 0x0f}, {"get-log-entries", 0x18}, {"get-opaque", 0x00}, {"get-option", 0x12}, {"get-pseudo-random", 0x13}, {"get-template", 0x1a}, {"import-wrapped", 0x0d}, {"put-asymmetric-key", 0x03}, {"put-authentication-key", 0x02}, {"put-mac-key", 0x14}, {"put-opaque", 0x01}, {"put-otp-aead-key", 0x23}, {"put-public-wrap-key", 0x54}, {"put-symmetric-key", 0x2f}, {"put-template", 0x1b}, {"put-wrap-key", 0x0e}, {"randomize-otp-aead", 0x1f}, {"reset-device", 0x1c}, {"rewrap-from-otp-aead-key", 0x20}, {"rewrap-to-otp-aead-key", 0x21}, {"set-option", 0x11}, {"sign-attestation-certificate", 0x22}, {"sign-ecdsa", 0x07}, {"sign-eddsa", 0x08}, {"sign-hmac", 0x16}, {"sign-pkcs", 0x05}, {"sign-pss", 0x06}, {"sign-ssh-certificate", 0x19}, {"unwrap-data", 0x26}, {"verify-hmac", 0x17}, {"wrap-data", 0x25}, }; static const struct { const char *name; yh_algorithm algorithm; } yh_algorithms[] = { {"aes128", YH_ALGO_AES128}, {"aes192", YH_ALGO_AES192}, {"aes256", YH_ALGO_AES256}, {"aes128-ccm-wrap", YH_ALGO_AES128_CCM_WRAP}, {"aes128-yubico-authentication", YH_ALGO_AES128_YUBICO_AUTHENTICATION}, {"aes128-yubico-otp", YH_ALGO_AES128_YUBICO_OTP}, {"aes192-ccm-wrap", YH_ALGO_AES192_CCM_WRAP}, {"aes192-yubico-otp", YH_ALGO_AES192_YUBICO_OTP}, {"aes256-ccm-wrap", YH_ALGO_AES256_CCM_WRAP}, {"aes256-yubico-otp", YH_ALGO_AES256_YUBICO_OTP}, {"aes-cbc", YH_ALGO_AES_CBC}, {"aes-ecb", YH_ALGO_AES_ECB}, {"aes-kwp", YH_ALGO_AES_KWP}, {"ecbp256", YH_ALGO_EC_BP256}, {"ecbp384", YH_ALGO_EC_BP384}, {"ecbp512", YH_ALGO_EC_BP512}, {"ecdh", YH_ALGO_EC_ECDH}, {"ecdsa-sha1", YH_ALGO_EC_ECDSA_SHA1}, {"ecdsa-sha256", YH_ALGO_EC_ECDSA_SHA256}, {"ecdsa-sha384", YH_ALGO_EC_ECDSA_SHA384}, {"ecdsa-sha512", YH_ALGO_EC_ECDSA_SHA512}, {"eck256", YH_ALGO_EC_K256}, {"ecp224", YH_ALGO_EC_P224}, {"ecp256", YH_ALGO_EC_P256}, {"ecp256-yubico-authentication", YH_ALGO_EC_P256_YUBICO_AUTHENTICATION}, {"ecp384", YH_ALGO_EC_P384}, {"ecp521", YH_ALGO_EC_P521}, {"ed25519", YH_ALGO_EC_ED25519}, {"hmac-sha1", YH_ALGO_HMAC_SHA1}, {"hmac-sha256", YH_ALGO_HMAC_SHA256}, {"hmac-sha384", YH_ALGO_HMAC_SHA384}, {"hmac-sha512", YH_ALGO_HMAC_SHA512}, {"mgf1-sha1", YH_ALGO_MGF1_SHA1}, {"mgf1-sha256", YH_ALGO_MGF1_SHA256}, {"mgf1-sha384", YH_ALGO_MGF1_SHA384}, {"mgf1-sha512", YH_ALGO_MGF1_SHA512}, {"opaque-data", YH_ALGO_OPAQUE_DATA}, {"opaque-x509-certificate", YH_ALGO_OPAQUE_X509_CERTIFICATE}, {"rsa-oaep-sha1", YH_ALGO_RSA_OAEP_SHA1}, {"rsa-oaep-sha256", YH_ALGO_RSA_OAEP_SHA256}, {"rsa-oaep-sha384", YH_ALGO_RSA_OAEP_SHA384}, {"rsa-oaep-sha512", YH_ALGO_RSA_OAEP_SHA512}, {"rsa-pkcs1-decrypt", YH_ALGO_RSA_PKCS1_DECRYPT}, {"rsa-pkcs1-sha1", YH_ALGO_RSA_PKCS1_SHA1}, {"rsa-pkcs1-sha256", YH_ALGO_RSA_PKCS1_SHA256}, {"rsa-pkcs1-sha384", YH_ALGO_RSA_PKCS1_SHA384}, {"rsa-pkcs1-sha512", YH_ALGO_RSA_PKCS1_SHA512}, {"rsa-pss-sha1", YH_ALGO_RSA_PSS_SHA1}, {"rsa-pss-sha256", YH_ALGO_RSA_PSS_SHA256}, {"rsa-pss-sha384", YH_ALGO_RSA_PSS_SHA384}, {"rsa-pss-sha512", YH_ALGO_RSA_PSS_SHA512}, {"rsa2048", YH_ALGO_RSA_2048}, {"rsa3072", YH_ALGO_RSA_3072}, {"rsa4096", YH_ALGO_RSA_4096}, {"template-ssh", YH_ALGO_TEMPLATE_SSH}, }; static const struct { const char *name; yh_object_type type; } yh_types[] = { {"authentication-key", YH_AUTHENTICATION_KEY}, {"asymmetric-key", YH_ASYMMETRIC_KEY}, {"hmac-key", YH_HMAC_KEY}, {"opaque", YH_OPAQUE}, {"otp-aead-key", YH_OTP_AEAD_KEY}, {"public-wrap-key", YH_PUBLIC_WRAP_KEY}, {"symmetric-key", YH_SYMMETRIC_KEY}, {"template", YH_TEMPLATE}, {"wrap-key", YH_WRAP_KEY}, }; static const struct { const char *name; yh_option option; } yh_options[] = { {"command-audit", YH_OPTION_COMMAND_AUDIT}, {"force-audit", YH_OPTION_FORCE_AUDIT}, {"algorithm-toggle", YH_OPTION_ALGORITHM_TOGGLE}, {"fips-mode", YH_OPTION_FIPS_MODE}, }; /// The object was generated on the device #define YH_ORIGIN_GENERATED 0x01 /// The object was imported into the device #define YH_ORIGIN_IMPORTED 0x02 /// The object was imported into the device under wrap. This is used in /// combination with objects original 'origin' #define YH_ORIGIN_IMPORTED_WRAPPED 0x10 /** * Return a string describing an error condition * * @param err #yh_rc error code * * @return String with descriptive error **/ const char *yh_strerror(yh_rc err); /** * Set verbosity level when executing commands. Default verbosity is *#YH_VERB_QUIET * * This function may be called prior to global library initialization to set * the debug level * * @param connector If not NULL, the verbosity of the specific connector will * be set * @param verbosity The desired level of debug output * * @return #YHR_SUCCESS * * @see YH_VERB_QUIET, YH_VERB_INTERMEDIATE, YH_VERB_CRYPTO, YH_VERB_RAW, * YH_VERB_INFO, YH_VERB_ERR, YH_VERB_ALL **/ yh_rc yh_set_verbosity(yh_connector *connector, uint8_t verbosity); /** * Get verbosity level when executing commands * * @param verbosity The verbosity level * * @return #YHR_SUCCESS if seccessful. * #YHR_INVALID_PARAMETERS if verbosity is NULL * * @see YH_VERB_QUIET, YH_VERB_INTERMEDIATE, YH_VERB_CRYPTO, YH_VERB_RAW, * YH_VERB_INFO, YH_VERB_ERR, YH_VERB_ALL **/ yh_rc yh_get_verbosity(uint8_t *verbosity); /** * Set file for debug output * * @param connector If not NULL, the debug messages will be written to the *specified output file * @param output The destination of the debug messages * * @return void **/ void yh_set_debug_output(yh_connector *connector, FILE *output); /** * Global library initialization * * @return #YHR_SUCCESS **/ yh_rc yh_init(void); /** * Global library clean up * * @return #YHR_SUCCESS **/ yh_rc yh_exit(void); /** * Instantiate a new connector * * @param url URL associated with this connector * @param connector Connector to the device * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if either the URL or the connector are NULL. * #YHR_GENERIC_ERROR if failed to load the backend. * #YHR_MEMORY_ERROR if failed to allocate memory for the connector. * #YHR_CONNECTION_ERROR if failed to create the connector */ yh_rc yh_init_connector(const char *url, yh_connector **connector); /** * Set connector options. * * Note that backend options are not supported with winhttp or USB connectors * * @param connector Connector to set an option on * @param opt Option to set. See #yh_connector_option * @param val Value of the option. Type of value is specific to the given *option * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if the connector or the value are NULL or if *the option is unknown. #YHR_CONNECTOR_ERROR if failed to set the option **/ yh_rc yh_set_connector_option(yh_connector *connector, yh_connector_option opt, const void *val); /** * Connect to the device through the specified connector * * @param connector Connector to the device * @param timeout Connection timeout in seconds * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if the connector does not exist. * See #yh_rc for other possible errors **/ yh_rc yh_connect(yh_connector *connector, int timeout); /** * Disconnect from a connector * * @param connector Connector from which to disconnect * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if the connector is NULL **/ yh_rc yh_disconnect(yh_connector *connector); /** * Send a plain (unencrypted) message to the device through a connector * * @param connector Connector to the device * @param cmd Command to send. See #yh_cmd * @param data Data to send * @param data_len length of data to send * @param response_cmd Response command * @param response Response data * @param response_len Length of response data * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * #YHR_BUFFER_TOO_SMALL if the actual response was longer than *response_len. See #yh_rc for other possible errors **/ yh_rc yh_send_plain_msg(yh_connector *connector, yh_cmd cmd, const uint8_t *data, size_t data_len, yh_cmd *response_cmd, uint8_t *response, size_t *response_len); /** * Send an encrypted message to the device over a session. The session has to be *authenticated * * @param session Session to send the message over * @param cmd Command to send * @param data Data to send * @param data_len Length of data to send * @param response_cmd Response command * @param response Response data * @param response_len Length of response data * * @return #YHR_SUCCESS if successful. See #yh_rc for possible errors **/ yh_rc yh_send_secure_msg(yh_session *session, yh_cmd cmd, const uint8_t *data, size_t data_len, yh_cmd *response_cmd, uint8_t *response, size_t *response_len); /** * Create a session that uses an encryption key and a MAC key derived from a *password * * @param connector Connector to the device * @param authkey_id Object ID of the Authentication Key used to authenticate *the session * @param password Password used to derive the session encryption key and MAC *key * @param password_len Length of the password in bytes * @param recreate_session If true, the session will be recreated if expired. *This caches the password in memory * @param session The created session * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if the connector, the password or the session *are NULL. #YHR_GENERIC_ERROR if failed to derive the session encryption key *and/or the MAC key or if PRNG related errors occur. #YHR_MEMORY_ERROR if *failed to allocate memory for the session. See #yh_rc for other possible *errors * * @see Session **/ yh_rc yh_create_session_derived(yh_connector *connector, uint16_t authkey_id, const uint8_t *password, size_t password_len, bool recreate_session, yh_session **session); /** * Create a session that uses the specified encryption key and MAC key to derive *session-specific keys * * @param connector Connector to the device * @param authkey_id Object ID of the Authentication Key used to authenticate *the session * @param key_enc Key used to derive the session encryption key * @param key_enc_len Length of key_enc * @param key_mac Key used to derive the session MAC keys * @param key_mac_len Length of key_mac * @param recreate_session If true, the session will be recreated if expired. *This caches the password in memory * @param session created session * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL or incorrect. * See #yh_rc for other possible errors * * @see Session, * Authentication *Key **/ yh_rc yh_create_session(yh_connector *connector, uint16_t authkey_id, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len, bool recreate_session, yh_session **session); /** * Create a session that uses named encryption keys from a platform-specific key *store to derive session-specific keys * * @param connector Connector to the device * @param authkey_id Object ID of the Authentication Key used to authenticate *the session * @param key_enc_name Name of key used to derive the session encryption key * @param key_mac_name Name of key used to derive the session MAC keys * @param session created session * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL or incorrect. * See #yh_rc for other possible errors * * @see Session, * Authentication *Key **/ yh_rc yh_create_session_ex(yh_connector *connector, uint16_t authkey_id, const char *key_enc_name, const char *key_mac_name, yh_session **session); /** * Begin creating a session where the session keys are calculated outside the *library. * * This function must be followed by yh_finish_create_session() to set the * session keys. * * If host_challenge_len is 0 when calling this function an 8 byte random *challenge is generated, and symmetric authentication is assumed. * * For asymmetric authentication the host challenge must be provided. * * @param connector Connector to the device * @param authkey_id Object ID of the Authentication Key used to authenticate *the session * @param context pointer to where context data is saved * @param host_challenge Host challenge * @param host_challenge_len Length of host challenge * @param card_cryptogram Card cryptogram from the device * @param card_cryptogram_len Length of card cryptogram * @param session created session * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * #YHR_MEMORY_ERROR if failed to allocate memory for the session. * See #yh_rc for other possible errors * * @see Session **/ yh_rc yh_begin_create_session(yh_connector *connector, uint16_t authkey_id, uint8_t **context, uint8_t *host_challenge, size_t *host_challenge_len, uint8_t *card_cryptogram, size_t *card_cryptogram_len, yh_session **session); /** * Finish creating a session. * * This function must be called after yh_begin_create_session(). * * For symmetric authentication this function will authenticate the session * with the device using the provided sesion keys and card cryptogram. * * For asymmetric authentication the card cryptogram must be validated *externally. * * @param session The session created with yh_begin_create_session() * @param key_senc Session encryption key used to encrypt the messages exchanged *with the device * @param key_senc_len Lenght of the encryption key. Must be #YH_KEY_LEN * @param key_smac Session MAC key used for creating the authentication tag for *each message * @param key_smac_len Length of the MAC key. Must be #YH_KEY_LEN * @param key_srmac Session return MAC key used for creating the authentication *tag for each response message * @param key_srmac_len Length of the return MAC key. Must be #YH_KEY_LEN * @param card_cryptogram Card cryptogram * @param card_cryptogram_len Length of card cryptogram * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL or any of the *key lengths are not #YH_KEY_LEN. * See #yh_rc for other possible errors * * @see Session **/ yh_rc yh_finish_create_session(yh_session *session, const uint8_t *key_senc, size_t key_senc_len, const uint8_t *key_smac, size_t key_smac_len, const uint8_t *key_srmac, size_t key_srmac_len, uint8_t *card_cryptogram, size_t card_cryptogram_len); /** * Utility function that gets the value and algorithm of the device public key * * @param connector Connector to the device * @param device_pubkey Value of the public key * @param device_pubkey_len Length of the public key in bytes * @param algorithm Algorithm of the key. * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * #YHR_BUFFER_TOO_SMALL if the actual key length was bigger than *device_pubkey_len. See #yh_rc for other possible errors **/ yh_rc yh_util_get_device_pubkey(yh_connector *connector, uint8_t *device_pubkey, size_t *device_pubkey_len, yh_algorithm *algorithm); /** * Utility function that derives an ec-p256 key pair from a password using the *following algorithm * * 1. Apply pkcs5_pbkdf2_hmac-sha256 on the password to derive a pseudo-random *private ec-p256 key * 2. Check that the derived key is a valid ec-p256 private key * 3. If not valid append a byte with the value 1 (2, 3, 4 etc for additional *failures) to the password and go to step 1 * 4. Calculate the corresponding public key from the private key and the *ec-p256 curve paramaters * * @param password The password bytes * @param password_len The password length * @param privkey Value of the private key * @param privkey_len Length of the private key in bytes * @param pubkey Value of the public key * @param pubkey_len Length of the public key in bytes * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. See #yh_rc for *other possible errors **/ yh_rc yh_util_derive_ec_p256_key(const uint8_t *password, size_t password_len, uint8_t *privkey, size_t privkey_len, uint8_t *pubkey, size_t pubkey_len); /** * Utility function that generates a random ec-p256 key pair * * @param privkey Value of the private key * @param privkey_len Length of the private key in bytes * @param pubkey Value of the public key * @param pubkey_len Length of the public key in bytes * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. See #yh_rc for *other possible errors **/ yh_rc yh_util_generate_ec_p256_key(uint8_t *privkey, size_t privkey_len, uint8_t *pubkey, size_t pubkey_len); /** * Create a session that uses the specified asymmetric key to derive *session-specific keys. * * @param connector Connector to the device * @param authkey_id Object ID of the Asymmetric Authentication Key used to *authenticate the session * @param privkey Private key of the client, used to derive the session *encryption key and authenticate the client * @param privkey_len Length of the private key. * @param device_pubkey Public key of the device, used to derive the session *encryption key and authenticate the device * @param device_pubkey_len Length of the device public key. * @param session created session * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL or incorrect. * See #yh_rc for other possible errors * * @see Session, * Authentication *Key **/ yh_rc yh_create_session_asym(yh_connector *connector, uint16_t authkey_id, const uint8_t *privkey, size_t privkey_len, const uint8_t *device_pubkey, size_t device_pubkey_len, yh_session **session); /** * Free data associated with the session * * @param session Pointer to the session to destroy * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if the session is NULL. * * @see Session **/ yh_rc yh_destroy_session(yh_session **session); /** * Deprecated, use yh_begin_create_session instead. **/ yh_rc yh_begin_create_session_ext(yh_connector *connector, uint16_t authkey_id, uint8_t **context, uint8_t *card_cryptogram, size_t card_cryptogram_len, yh_session **session); /** * Deprecated, use yh_finish_create_session instead. **/ yh_rc yh_finish_create_session_ext(yh_connector *connector, yh_session *session, const uint8_t *key_senc, size_t key_senc_len, const uint8_t *key_smac, size_t key_smac_len, const uint8_t *key_srmac, size_t key_srmac_len, uint8_t *card_cryptogram, size_t card_cryptogram_len); /** * Deprecated, calling this function has no effect. **/ yh_rc yh_authenticate_session(yh_session *session); // Utility and convenience functions below /** * Get device info in a struct * * @param connector Connector to the device * @param device_info Device info * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if the connector or device_info is NULL. * #YHR_BUFFER_TOO_SMALL if n_algorithms is smaller than the number of *actually supported algorithms. See #yh_rc for other possible errors. * * @see Algorithms **/ yh_rc yh_util_get_device_info_ex(yh_connector *connector, yh_device_info *device_info); /** * Get device version, device serial number, supported algorithms and available *log entries. * * @param connector Connector to the device * @param major Device major version number * @param minor Device minor version number * @param patch Device build version number * @param serial Device serial number * @param log_total Total number of log entries * @param log_used Number of written log entries * @param algorithms List of supported algorithms * @param n_algorithms Number of supported algorithms * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if the connector is NULL. * #YHR_BUFFER_TOO_SMALL if n_algorithms is smaller than the number of *actually supported algorithms. See #yh_rc for other possible errors. * * @see Algorithms **/ yh_rc yh_util_get_device_info(yh_connector *connector, uint8_t *major, uint8_t *minor, uint8_t *patch, uint32_t *serial, uint8_t *log_total, uint8_t *log_used, yh_algorithm *algorithms, size_t *n_algorithms); /** * Get device version, part number (chip designator) as required ny FIPS * * @param connector Connector to the device * @param part_number Part number (chip designator) * @param part_number_len Size of part_number * * @return #YHR_SUCCESS if successful or of part_number is NULL * #YHR_DEVICE_INVALID_COMMAND if firmware version does not support the *command * #YHR_INVALID_PARAMETER if the connector is NULL. * #YH_INVALID_DEVICE_INVALID_DATA If returned part_number is less than *12 bytes * #YHR_BUFFER_TOO_SMALL if part_number is smaller than 13 bytes **/ yh_rc yh_util_get_partnumber(yh_connector *connector, char *part_number, size_t *part_number_len); /** * List objects accessible from the session * * @param session Authenticated session to use * @param id Object ID to filter by (0 to not filter by ID) * @param type Object type to filter by (0 to not filter by type). See *#yh_object_type * @param domains Domains to filter by (0 to not filter by domain) * @param capabilities Capabilities to filter by (0 to not filter by *capabilities). See #yh_capabilities * @param algorithm Algorithm to filter by (0 to not filter by algorithm) * @param label Label to filter by * @param objects Array of objects returned * @param n_objects Max number of objects (will be set to number found on *return) * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * #YHR_BUFFER_TOO_SMALL if n_objects is smaller than the number of *objects found. See #yh_rc for other possible errors. * * @see Objects, * Domains, * Capabilities, * Algorithms, * Labels **/ yh_rc yh_util_list_objects(yh_session *session, uint16_t id, yh_object_type type, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const char *label, yh_object_descriptor *objects, size_t *n_objects); /** * Get metadata of the object with the specified Object ID and Type * * @param session Authenticated session to use * @param id Object ID of the object to get * @param type Object type. See #yh_object_type * @param object Object information * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if the session is NULL. * See #yh_rc for other possible errors. * * @see Objects **/ yh_rc yh_util_get_object_info(yh_session *session, uint16_t id, yh_object_type type, yh_object_descriptor *object); /** * Get the value of the public key with the specified Object ID * * @param session Authenticated session to use * @param id Object ID of the public key * @param data Value of the public key * @param data_len Length of the public key in bytes * @param algorithm Algorithm of the key * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * #YHR_BUFFER_TOO_SMALL if the actual key length was bigger than *data_len. See #yh_rc for other possible errors **/ yh_rc yh_util_get_public_key(yh_session *session, uint16_t id, uint8_t *data, size_t *data_len, yh_algorithm *algorithm); /** * Get the value of the public key with the specified Object ID and type * * @param session Authenticated session to use * @param id Object ID of the public key * @param type Object type of the public key * @param data Value of the public key * @param data_len Length of the public key in bytes * @param algorithm Algorithm of the key * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * #YHR_BUFFER_TOO_SMALL if the actual key length was bigger than *data_len. See #yh_rc for other possible errors **/ yh_rc yh_util_get_public_key_ex(yh_session *session, yh_object_type type, uint16_t id, uint8_t *data, size_t *data_len, yh_algorithm *algorithm); /** * Close a session * * @param session Session to close * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if the session is NULL. * See #yh_rc for other possible errors **/ yh_rc yh_util_close_session(yh_session *session); /** * Sign data using RSA-PKCS#1v1.5 * * in is either a raw hashed message (sha1, sha256, sha384 or sha512) *or that with correct digestinfo pre-pended * * @param session Authenticated session to use * @param key_id Object ID of the signing key * @param hashed true if data is only hashed * @param in data to sign * @param in_len length of data to sign * @param out signed data * @param out_len length of signed data * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS input parameters are NULL or if *in_len is not 20, 32, 48 or 64. See #yh_rc for other possible errors **/ yh_rc yh_util_sign_pkcs1v1_5(yh_session *session, uint16_t key_id, bool hashed, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len); /** * Sign data using RSA-PSS * * in is a raw hashed message (sha1, sha256, sha384 or sha512) * * @param session Authenticated session to use * @param key_id Object ID of the signing key * @param in Data to sign * @param in_len Length of data to sign * @param out Signed data * @param out_len Length of signed data * @param salt_len Length of salt * @param mgf1Algo Algorithm for mgf1 (mask generation function for PSS) * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS input parameters are NULL or if *in_len is not 20, 32, 48 or 64. See #yh_rc for other possible errors * * @see PSS *specifications **/ yh_rc yh_util_sign_pss(yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len, size_t salt_len, yh_algorithm mgf1Algo); /** * Sign data using ECDSA * * in is a raw hashed message, a truncated hash to the curve length or *a padded hash to the curve length * * @param session Authenticated session to use * @param key_id Object ID of the signing key * @param in Data to sign * @param in_len Length of data to sign * @param out Signed data * @param out_len Length of signed data * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS input parameters are NULL or if *in_len is not 20, 28, 34, 48, 64 or 66. See #yh_rc for other possible *errors **/ yh_rc yh_util_sign_ecdsa(yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len); /** * Sign data using EdDSA * * @param session Authenticated session to use * @param key_id Object ID of the signing key * @param in Data to sign * @param in_len Length of data to sign * @param out Signed data * @param out_len Length of signed data * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS input parameters are NULL or if *in_len is bigger than YH_MSG_BUF_SIZE-2. See #yh_rc for other *possible errors **/ yh_rc yh_util_sign_eddsa(yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len); /** * Sign data using HMAC * * @param session Authenticated session to use * @param key_id Object ID of the signing key * @param in Data to HMAC * @param in_len Length of data to hmac * @param out HMAC * @param out_len Length of HMAC * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS input parameters are NULL or if *in_len is bigger than YH_MSG_BUF_SIZE-2. See #yh_rc for other *possible errors **/ yh_rc yh_util_sign_hmac(yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len); /** * Get a fixed number of pseudo-random bytes from the device * * @param session Authenticated session to use * @param len Length of pseudo-random data to get * @param out Pseudo-random data out * @param out_len Length of pseudo-random data * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS input parameters are NULL. * See #yh_rc for other possible errors **/ yh_rc yh_util_get_pseudo_random(yh_session *session, size_t len, uint8_t *out, size_t *out_len); /** * Import an AES key into the device * * @param session Authenticated session to use * @param key_id Object ID the key. 0 if Object ID should be generated by *the device * @param label Label of the key. Maximum length is #YH_OBJ_LABEL_LEN * @param domains Domains to which the key belongs specified as an unsigned int. *See #yh_string_to_domains() * @param capabilities Capabilities of the key. See *#yh_string_to_capabilities() * @param algorithm Algorithm of the key to import. Must be one of: *#YH_ALGO_AES128, #YH_ALGO_AES192 or #YH_ALGO_AES256 * @param key The key to import. * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS input parameters are NULL or the algorithm is *not one of #YH_ALGO_AES128, #YH_ALGO_AES192 or #YH_ALGO_AES256. See *#yh_rc for other possible errors **/ yh_rc yh_util_import_aes_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const uint8_t *key); /** * Import an RSA key into the device * * @param session Authenticated session to use * @param key_id Object ID the key. 0 if Object ID should be generated by *the device * @param label Label of the key. Maximum length is #YH_OBJ_LABEL_LEN * @param domains Domains to which the key belongs specified as an unsigned int. *See #yh_string_to_domains() * @param capabilities Capabilities of the key. See *#yh_string_to_capabilities() * @param algorithm Algorithm of the key to import. Must be one of: *#YH_ALGO_RSA_2048, #YH_ALGO_RSA_3072 or #YH_ALGO_RSA_4096 * @param p P component of the RSA key to import * @param q Q component of the RSA key to import * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS input parameters are NULL or the algorithm is *not one of #YH_ALGO_RSA_2048, #YH_ALGO_RSA_3072 or #YH_ALGO_RSA_4096. See *#yh_rc for other possible errors **/ yh_rc yh_util_import_rsa_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const uint8_t *p, const uint8_t *q); /** * Import an Elliptic Curve key into the device * * @param session Authenticated session to use * @param key_id Object ID of the key. 0 if the Object ID should be generated *by the device * @param label Label of the key. Maximum length is #YH_OBJ_LABEL_LEN * @param domains Domains to which the key belongs specified as *an unsigned int. See #yh_string_to_domains() * @param capabilities Capabilities of the key. See *#yh_string_to_capabilities() * @param algorithm Algorithm of the key to import. Must be one of: *#YH_ALGO_EC_P224, #YH_ALGO_EC_P256, #YH_ALGO_EC_K256, #YH_ALGO_EC_BP256, *#YH_ALGO_EC_P384, #YH_ALGO_EC_BP384, #YH_ALGO_EC_BP512 or #YH_ALGO_EC_P521 * @param s the EC key to import * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS input parameters are NULL or the algorithm is *not one of #YH_ALGO_EC_P224, #YH_ALGO_EC_P256, #YH_ALGO_EC_K256, *#YH_ALGO_EC_BP256, #YH_ALGO_EC_P384, #YH_ALGO_EC_BP384, #YH_ALGO_EC_BP512 or *#YH_ALGO_EC_P521. * See #yh_rc for other possible errors **/ yh_rc yh_util_import_ec_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const uint8_t *s); /** * Import an ED key into the device * * @param session Authenticated session to use * @param key_id Object ID of the key will have. 0 if the Object ID should be *generated by the device * @param label Label of the key. Maximum length is #YH_OBJ_LABEL_LEN * @param domains Domains to which the key belongs. See #yh_string_to_domains() * @param capabilities Capabilities of the key. See *#yh_string_to_capabilities() * @param algorithm Algorithm of the key to import. Must be #YH_ALGO_EC_ED25519 * @param k the ED key to import * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS input parameters are NULL or the algorithm is *not #YH_ALGO_EC_ED25519. See #yh_rc for other possible errors **/ yh_rc yh_util_import_ed_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const uint8_t *k); /** * Import an HMAC key into the device * * @param session Authenticated session to use * @param key_id Object ID of the key. 0 if the Object ID should be *generated by the device * @param label Label of the key. Maxium length is #YH_OBJ_LABEL_LEN * @param domains Domains to which the key belongs. See #yh_string_to_domains() * @param capabilities Capabilities of the key. See *#yh_string_to_capabilities() * @param algorithm Algorithm of the key to import. Must be one of: *#YH_ALGO_HMAC_SHA1, #YH_ALGO_HMAC_SHA256, #YH_ALGO_HMAC_SHA384 *or #YH_ALGO_HMAC_SHA512 * @param key The HMAC key to import * @param key_len Length of the HMAC key to import * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS input parameters are NULL. * See #yh_rc for other possible errors **/ yh_rc yh_util_import_hmac_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const uint8_t *key, size_t key_len); /** * Generate an AES key in the device * * @param session Authenticated session to use * @param key_id Object ID of the key. 0 if the Object ID should be *generated by the device * @param label Label of the key. Maximum length is #YH_OBJ_LABEL_LEN * @param domains Domains to which the key belongs. See #yh_string_to_domains() * @param capabilities Capabilities of the key. See *#yh_string_to_capabilities() * @param algorithm Algorithm to use to generate the AES key. Supported *algorithms: #YH_ALGO_AES128, #YH_ALGO_AES192 and #YH_ALGO_AES256 * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS input parameters are NULL or the algorithm is *not one of #YH_ALGO_AES128, #YH_ALGO_AES192 or #YH_ALGO_AES256. * See #yh_rc for other possible errors **/ yh_rc yh_util_generate_aes_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm); /** * Generate an RSA key in the device * * @param session Authenticated session to use * @param key_id Object ID of the key. 0 if the Object ID should be *generated by the device * @param label Label of the key. Maximum length is #YH_OBJ_LABEL_LEN * @param domains Domains to which the key belongs. See #yh_string_to_domains() * @param capabilities Capabilities of the key. See *#yh_string_to_capabilities() * @param algorithm Algorithm to use to generate the RSA key. Supported *algorithms: #YH_ALGO_RSA_2048, #YH_ALGO_RSA_3072 and #YH_ALGO_RSA_4096 * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS input parameters are NULL or the algorithm is *not one of #YH_ALGO_RSA_2048, #YH_ALGO_RSA_3072 or #YH_ALGO_RSA_4096. * See #yh_rc for other possible errors **/ yh_rc yh_util_generate_rsa_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm); /** * Generate an Elliptic Curve key in the device * * @param session Authenticated session to use * @param key_id Object ID of the key. 0 if the Object ID should be generated *by the device * @param label Label of the key. Maximum length is #YH_OBJ_LABEL_LEN * @param domains Domains to which the key belongs. See #yh_string_to_domains() * @param capabilities Capabilities of the key. See *#yh_string_to_capabilities() * @param algorithm Algorithm to use to generate the EC key. Supported *algorithm: #YH_ALGO_EC_P224, #YH_ALGO_EC_P256, #YH_ALGO_EC_K256, *#YH_ALGO_EC_BP256, #YH_ALGO_EC_P384, #YH_ALGO_EC_BP384, #YH_ALGO_EC_BP512 and *#YH_ALGO_EC_P521. * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS input parameters are NULL or the algorithm is *not one of #YH_ALGO_EC_P224, #YH_ALGO_EC_P256, #YH_ALGO_EC_K256, *#YH_ALGO_EC_BP256, #YH_ALGO_EC_P384, #YH_ALGO_EC_BP384, #YH_ALGO_EC_BP512 or *#YH_ALGO_EC_P521. * See #yh_rc for other possible errors **/ yh_rc yh_util_generate_ec_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm); /** * Generate an ED key in the device * * @param session Authenticated session to use * @param key_id Object ID of the key. 0 if the Object ID should be generated *by the device * @param label Label for the key. Maximum length #YH_OBJ_LABEL_LEN * @param domains Domains to which the key belongs. See #yh_string_to_domains() * @param capabilities Capabilities of the ED key. See *#yh_string_to_capabilities() * @param algorithm Algorithm to use to generate the ED key. Supported *algorithm: #YH_ALGO_EC_ED25519 * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS input parameters are NULL or the algorithm is *not #YH_ALGO_EC_ED25519. * See #yh_rc for other possible errors **/ yh_rc yh_util_generate_ed_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm); /** * Verify a generated HMAC * * @param session Authenticated session to use * @param key_id Object ID of the HMAC key * @param signature HMAC signature (20, 32, 48 or 64 bytes) * @param signature_len length of HMAC signature * @param data data to verify * @param data_len length of data to verify * @param verified true if verification succeeded * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS input parameters are NULL or if *signature_len + data_len is too long. * See #yh_rc for other possible errors * **/ yh_rc yh_util_verify_hmac(yh_session *session, uint16_t key_id, const uint8_t *signature, size_t signature_len, const uint8_t *data, size_t data_len, bool *verified); /** * Generate an HMAC key in the device * * @param session Authenticated session to use * @param key_id Object ID of the key. 0 if the Object ID should be *generated by the device * @param label Label of the key. Maximum length #YH_OBJ_LABEL_LEN * @param domains Domains to which the key belongs. See #yh_string_to_domains() * @param capabilities Capabilities of the key. See *#yh_string_to_capabilities() * @param algorithm Algorithm to use to generate the HMAC key. Supported *algorithims: #YH_ALGO_HMAC_SHA1, #YH_ALGO_HMAC_SHA256, #YH_ALGO_HMAC_SHA384 *and #YH_ALGO_HMAC_SHA512 * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS input parameters are NULL. * See #yh_rc for other possible errors * **/ yh_rc yh_util_generate_hmac_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm); /** * Decrypt data that was encrypted using RSA-PKCS#1v1.5 * * @param session Authenticated session to use * @param key_id Object ID of the RSA key to use for decryption * @param in Encrypted data * @param in_len Length of encrypted data * @param out Decrypted data * @param out_len Length of decrypted data * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS input parameters are NULL or if *in_len is bigger than #YH_MSG_BUF_SIZE-2. * See #yh_rc for other possible errors * **/ yh_rc yh_util_decrypt_pkcs1v1_5(yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len); /** * Decrypt data using RSA-OAEP * * @param session Authenticated session to use * @param key_id Object ID of the RSA key to use for decryption * @param in Encrypted data * @param in_len Length of encrypted data. Must be 256, 384 or 512 * @param out Decrypted data * @param out_len Length of decrypted data * @param label Hash of OAEP label. Hash function must be SHA-1, SHA-256, *SHA-384 or SHA-512 * @param label_len Length of hash of OAEP label. Must be 20, 32, 48 or 64 * @param mgf1Algo MGF1 algorithm * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS input parameters are NULL. * #YHR_WRONG_LENGTH if in_len or label_len are not *what expected. * See #yh_rc for other possible errors * **/ yh_rc yh_util_decrypt_oaep(yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len, const uint8_t *label, size_t label_len, yh_algorithm mgf1Algo); /** * Derive an ECDH key from a private EC key on the device and a provided public *EC key * * @param session Authenticated session to use * @param key_id Object ID of the EC private key to use for ECDH derivation * @param in Public key of another EC key-pair * @param in_len Length of public key * @param out Shared secret ECDH key * @param out_len Length of the shared ECDH key * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS input parameters are NULL or if *in_len is bigger than #YH_MSG_BUF_SIZE-2. * See #yh_rc for other possible errors * **/ yh_rc yh_util_derive_ecdh(yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len); /** * Delete an object in the device * * @param session Authenticated session to use * @param id Object ID of the object to delete * @param type Type of object to delete. See #yh_object_type * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if session is NULL. * See #yh_rc for other possible errors * **/ yh_rc yh_util_delete_object(yh_session *session, uint16_t id, yh_object_type type); /** * Export an object under wrap from the device * * @param session Authenticated session to use * @param wrapping_key_id Object ID of the Wrap Key to use to wrap the object * @param target_type Type of the object to be exported. See #yh_object_type * @param target_id Object ID of the object to be exported * @param out Wrapped data * @param out_len Length of wrapped data * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * See #yh_rc for other possible errors **/ yh_rc yh_util_export_wrapped(yh_session *session, uint16_t wrapping_key_id, yh_object_type target_type, uint16_t target_id, uint8_t *out, size_t *out_len); /** * Export an object under wrap from the device with the option to include the *ED25519 seed * * @param session Authenticated session to use * @param wrapping_key_id Object ID of the Wrap Key to use to wrap the object * @param target_type Type of the object to be exported. See #yh_object_type * @param target_id Object ID of the object to be exported * @param format Curently supported formats: 0=legacy 1=include ED25519 seed * @param out Wrapped data * @param out_len Length of wrapped data * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * See #yh_rc for other possible errors **/ yh_rc yh_util_export_wrapped_ex(yh_session *session, uint16_t wrapping_key_id, yh_object_type target_type, uint16_t target_id, uint8_t format, uint8_t *out, size_t *out_len); /** * Import a wrapped object into the device. The object should have been *previously exported by #yh_util_export_wrapped() * * @param session Authenticated session to use * @param wrapping_key_id Object ID of the Wrap Key to use to unwrap the object * @param in Wrapped data * @param in_len Length of wrapped data * @param target_type Type of the imported object * @param target_id Object ID of the imported object * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * See #yh_rc for other possible errors **/ yh_rc yh_util_import_wrapped(yh_session *session, uint16_t wrapping_key_id, const uint8_t *in, size_t in_len, yh_object_type *target_type, uint16_t *target_id); /** * Export a (a)symmetric key material using an RSA wrap key, meta data or *properties, like domains and capabilities, are not included. Only asymmetric *and symmetric key objects are valid targets. * * @param session Authenticated session to use * @param wrapping_key_id Object ID of the Wrap Key to use to wrap the object * @param target_type Type of the target key object * @param target_id Object ID of the target key object * @param aes Algorithm of the ephemeral AES key. Can be #YH_ALGO_AES128, *#YH_ALGO_AES192 or #YH_ALGO_AES256 * @param hash Hash algorithm. One of #YH_ALGO_RSA_OAEP_SHA1, *#YH_ALGO_RSA_OAEP_SHA256, #YH_ALGO_RSA_OAEP_SHA384 or #YH_ALGO_RSA_OAEP_SHA512 * @param mgf1 MGF1 algorithm. One of #YH_ALGO_MGF1_SHA1, #YH_ALGO_MGF1_SHA256, *#YH_ALGO_MGF1_SHA384 or #YH_ALGO_MGF1_SHA512 * @param label Label for the MGF1 algorithm * @param label_len Label length * @param out Wrapped key object bytes * @param out_len Length of the wrapped key * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL or if the * command is not supported. * See #yh_rc for other possible errors **/ yh_rc yh_util_get_rsa_wrapped_key(yh_session *session, uint16_t wrap_key_id, yh_object_type target_type, uint16_t target_id, yh_algorithm aes, yh_algorithm hash, yh_algorithm mgf1, const uint8_t *oaep_label, size_t oaep_label_len, uint8_t *out, size_t *out_len); /** * Export an object using an RSA wrap key. The wrapped object contain all meta *data and properties, like domains and capabilities * * @param session Authenticated session to use * @param wrapping_key_id Object ID of the Wrap Key to use to wrap the object * @param target_type Type of the target object * @param target_id Object ID of the target object * @param aes Algorithm of the ephemeral AES key. Can be #YH_ALGO_AES128, *#YH_ALGO_AES192 or #YH_ALGO_AES256 * @param hash Hash algorithm. One of #YH_ALGO_RSA_OAEP_SHA1, *#YH_ALGO_RSA_OAEP_SHA256, #YH_ALGO_RSA_OAEP_SHA384 or #YH_ALGO_RSA_OAEP_SHA512 * @param mgf1 MGF1 algorithm. One of #YH_ALGO_MGF1_SHA1, #YH_ALGO_MGF1_SHA256, *#YH_ALGO_MGF1_SHA384 or #YH_ALGO_MGF1_SHA512 * @param label Label for the MGF1 algorithm * @param label_len Label length * @param out Wrapped object bytes * @param out_len Length of the wrapped object * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL or if the * command is not supported. * See #yh_rc for other possible errors **/ yh_rc yh_util_export_rsa_wrapped(yh_session *session, uint16_t wrap_key_id, yh_object_type target_type, uint16_t target_id, yh_algorithm aes, yh_algorithm hash, yh_algorithm mgf1, const uint8_t *oaep_label, size_t oaep_label_len, uint8_t *out, size_t *out_len); /** * Import an object using an RSA wrap key. * * @param session Authenticated session to use * @param wrapping_key_id Object ID of the Wrap Key to use to unwrap the object * @param hash Hash algorithm. One of #YH_ALGO_RSA_OAEP_SHA1, *#YH_ALGO_RSA_OAEP_SHA256, #YH_ALGO_RSA_OAEP_SHA384 or #YH_ALGO_RSA_OAEP_SHA512 * @param mgf1 MGF1 algorithm. One of #YH_ALGO_MGF1_SHA1, #YH_ALGO_MGF1_SHA256, *#YH_ALGO_MGF1_SHA384 or #YH_ALGO_MGF1_SHA512 * @param label Label for the MGF1 algorithm * @param label_len Label length * @param in Wrapped object bytes * @param in_len Length of the wrapped object * @param target_type Type of the target object * @param target_id Object ID of the target object * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL or if the * command is not supported. * See #yh_rc for other possible errors **/ yh_rc yh_util_import_rsa_wrapped(yh_session *session, uint16_t wrapping_key_id, yh_algorithm hash, yh_algorithm mgf1, const uint8_t *label, size_t label_len, const uint8_t *in, size_t in_len, yh_object_type *target_type, uint16_t *target_id); /** * Import an (a)symmetric key using an RSA wrap key. * * @param session Authenticated session to use * @param wrapping_key_id Object ID of the Wrap Key to use to unwrap the object * @param type Type of object to import. One of #YH_SYMMETRIC_KEY or *#YH_ASYMMETRIC_KEY * @param target_id Object ID of object to import * @param algo Key algorithm of object to import * @param label Label of object to import * @param domains Domains of object to import * @param capabilities of object to import * @param hash Hash algorithm. One of #YH_ALGO_RSA_OAEP_SHA1, *#YH_ALGO_RSA_OAEP_SHA256, #YH_ALGO_RSA_OAEP_SHA384 or #YH_ALGO_RSA_OAEP_SHA512 * @param mgf1 MGF1 algorithm. One of #YH_ALGO_MGF1_SHA1, #YH_ALGO_MGF1_SHA256, *#YH_ALGO_MGF1_SHA384 or #YH_ALGO_MGF1_SHA512 * @param oaep_label Label for the MGF1 algorithm * @param oaep_label_len Label length * @param in Wrapped object bytes * @param in_len Length of the wrapped object * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL or if the * command is not supported. * See #yh_rc for other possible errors **/ yh_rc yh_util_put_rsa_wrapped_key( yh_session *session, uint16_t wrapping_key_id, yh_object_type type, uint16_t *target_id, yh_algorithm algo, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm hash, yh_algorithm mgf1, const uint8_t *oaep_label, size_t oaep_label_len, const uint8_t *in, size_t in_len); /** * Import a Wrap Key into the device * * @param session Authenticated session to use * @param key_id Object ID the Wrap Key. 0 if the Object ID should be generated *by the device * @param label Label of the Wrap Key. Maximum length is #YH_OBJ_LABEL_LEN * @param domains Domains where the Wrap Key will be operating within. See *#yh_string_to_domains() * @param capabilities Capabilities of the Wrap Key. See *#yh_string_to_capabilities() * @param algorithm Algorithm of the Wrap Key. Supported algorithms: *#YH_ALGO_AES128_CCM_WRAP, #YH_ALGO_AES192_CCM_WRAP, *#YH_ALGO_AES256_CCM_WRAP, #YH_ALGO_RSA_2048, #YH_ALGO_RSA_3072 and * #YH_ALGO_RSA_4096 * @param delegated_capabilities Delegated capabilities of the Wrap Key. See *#yh_string_to_capabilities() * @param in the Wrap Key to import * @param in_len Length of the Wrap Key to import * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL, in_len *is not what expected based on the algorithm and if the algorithms is not one *of #YH_ALGO_AES128_CCM_WRAP, #YH_ALGO_AES192_CCM_WRAP, *#YH_ALGO_AES256_CCM_WRAP or an RSA key algorithm. #YHR_INVALID_PARAMETERS will * also be returned if the firmware version does not support RSA wrap keys. * See #yh_rc for other possible errors **/ yh_rc yh_util_import_wrap_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const yh_capabilities *delegated_capabilities, const uint8_t *in, size_t in_len); /** * Import a public RSA key as a public wrap Key into the device * * @param session Authenticated session to use * @param key_id Object ID the Wrap Key. 0 if the Object ID should be generated *by the device * @param label Label of the Wrap Key. Maximum length is #YH_OBJ_LABEL_LEN * @param domains Domains where the Wrap Key will be operating within. See *#yh_string_to_domains() * @param capabilities Capabilities of the Wrap Key. See *#yh_string_to_capabilities() * @param algorithm Algorithm of the Public Wrap Key. Supported algorithms: *#YH_ALGO_RSA_2048, #YH_ALGO_RSA_3072 and #YH_ALGO_RSA_4096 * @param delegated_capabilities Delegated capabilities of the Wrap Key. See *#yh_string_to_capabilities() * @param in the Public Wrap Key to import in PEM format * @param in_len Length of the Wrap Key to import * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL, in_len *is not what expected based on the algorithm and if the algorithms is not one *of #YH_ALGO_RSA_2048, #YH_ALGO_RSA_3072 or #YH_ALGO_RSA_4096. * See #yh_rc for other possible errors **/ yh_rc yh_util_import_public_wrap_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const yh_capabilities *delegated_capabilities, const uint8_t *in, size_t in_len); /** * Generate a Wrap Key that can be used for export, import, wrap data and unwrap *data in the device. * * @param session Authenticated session to use * @param key_id Object ID of the Wrap Key. 0 if the Object ID should be *generated by the device * @param label Label of the Wrap Key. Maximum length #YH_OBJ_LABEL_LEN * @param domains Domains where the Wrap Key will be operating within. See *#yh_string_to_domains() * @param capabilities Capabilities of the Wrap Key. See *#yh_string_to_capabilities() * @param algorithm Algorithm used to generate the Wrap Key * @param delegated_capabilities Delegated capabilitites of the Wrap Key. See *#yh_string_to_capabilities() * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * See #yh_rc for other possible errors * * @see yh_object_type **/ yh_rc yh_util_generate_wrap_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const yh_capabilities *delegated_capabilities); /** * Get audit logs from the device. * * When audit enforce is set, if the log buffer is full, no new operations *(other than authentication operations) can be performed unless the log entries *are read by this command and then the log index is set by calling *#yh_util_set_log_index(). * * @param session Authenticated session to use * @param unlogged_boot Number of unlogged boot events. Used if the log buffer *is full and audit enforce is set * @param unlogged_auth Number of unlogged authentication events. Used if the *log buffer is full and audit enforce is set * @param out Log entries on the device * @param n_items Number of log entries * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * #YHR_BUFFER_TOO_SMALL if n_items is smaller than the actual *number of retrieved log entries. * See #yh_rc for other possible errors **/ yh_rc yh_util_get_log_entries(yh_session *session, uint16_t *unlogged_boot, uint16_t *unlogged_auth, yh_log_entry *out, size_t *n_items); /** * Set the index of the last extracted log entry. * * This function should be called after #yh_util_get_log_entries() to inform the *device what the last extracted log entry is so new logs can be written. This *is used when forced auditing is enabled. * * @param session Authenticated session to use * @param index index to set. Should be the same index as the last entry *extracted using #yh_util_get_log_entries() * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if the session is NULL. * See #yh_rc for other possible errors **/ yh_rc yh_util_set_log_index(yh_session *session, uint16_t index); /** * Get an #YH_OPAQUE object (like an X.509 certificate) from the device * * @param session Authenticated session to use * @param object_id Object ID of the Opaque object * @param out the retrieved Opaque object * @param out_len Length of the retrieved Opaque object * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * See #yh_rc for other possible errors **/ yh_rc yh_util_get_opaque(yh_session *session, uint16_t object_id, uint8_t *out, size_t *out_len); /** * Import an #YH_OPAQUE object into the device * * @param session Authenticated session to use * @param object_id Object ID of the Opaque object. 0 if the Object ID should be *generated by the device * @param label Label of the Opaque object. Maximum length is #YH_OBJ_LABEL_LEN * @param domains Domains the Opaque object will be operating within. See *#yh_string_to_domains() * @param capabilities Capabilities of the Opaque object. See *#yh_string_to_capabilities() * @param algorithm Algorithm of the Opaque object * @param in the Opaque object to import * @param in_len Length of the Opaque object to import * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL or *in_len is too big. * See #yh_rc for other possible errors **/ yh_rc yh_util_import_opaque(yh_session *session, uint16_t *object_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const uint8_t *in, size_t in_len); /** * Get an #YH_OPAQUE object (like an X.509 certificate) from the device with an *option to decompress the data * * @param session Authenticated session to use * @param object_id Object ID of the Opaque object * @param out the retrieved Opaque object * @param out_len Length of the retrieved Opaque object * @param stored_len Length of the stored opaque object (compressed objects have *stored_len shorter than out_len) * @param compress Try decompressing the object data before returning it * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * See #yh_rc for other possible errors **/ yh_rc yh_util_get_opaque_ex(yh_session *session, uint16_t object_id, uint8_t *out, size_t *out_len, size_t *stored_len, bool try_decompress); /** * Import an #YH_OPAQUE object into the device with an option to compress the *data before import * * @param session Authenticated session to use * @param object_id Object ID of the Opaque object. 0 if the Object ID should be *generated by the device * @param label Label of the Opaque object. Maximum length is #YH_OBJ_LABEL_LEN * @param domains Domains the Opaque object will be operating within. See *#yh_string_to_domains() * @param capabilities Capabilities of the Opaque object. See *#yh_string_to_capabilities() * @param algorithm Algorithm of the Opaque object * @param in the Opaque object to import * @param in_len Length of the Opaque object to import * @param compress Compression option for X509 certificates * @param import_len Number of bytes imported * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL or *in_len is too big. * See #yh_rc for other possible errors **/ yh_rc yh_util_import_opaque_ex(yh_session *session, uint16_t *object_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const uint8_t *in, size_t in_len, yh_compress_option compress, size_t *import_len); /** * Sign an SSH Certificate request. The function produces a signature that can *then be used to produce the SSH Certificate * * @param session Authenticated session to use * @param key_id Object ID of the key used to sign the request * @param template_id Object ID of the template to use as a certificate template * @param sig_algo Signature algorithm to use to sign the certificate request * @param in Certificate request * @param in_len Length of the certificate request * @param out Signature * @param out_len Length of the signature * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL or *in_len is too big. * See #yh_rc for other possible errors **/ yh_rc yh_util_sign_ssh_certificate(yh_session *session, uint16_t key_id, uint16_t template_id, yh_algorithm sig_algo, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len); /** * Import an #YH_AUTHENTICATION_KEY into the device * * @param session Authenticated session to use * @param key_id Object ID of the imported key. 0 if the Object ID should be *generated by the device * @param label Label of the key. Maximum length is #YH_OBJ_LABEL_LEN * @param domains Domains to which the key belongs. See #yh_string_to_domains() * @param capabilities Capabilities of the key. See #yh_string_to_capabilities() * @param delegated_capabilities Delegated capabilities of the key. See *#yh_string_to_capabilities() * @param key_enc Long lived encryption key of the Authentication Key to import * @param key_enc_len Length of the encryption key. Must be #YH_KEY_LEN * @param key_mac Long lived MAC key of the Authentication Key to import * @param key_mac_len Length of the MAC key. Must be #YH_KEY_LEN * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL or if *key_enc_len or key_mac_len are not the expected values. * See #yh_rc for other possible errors * * @see Authentication *Key **/ yh_rc yh_util_import_authentication_key( yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, const yh_capabilities *delegated_capabilities, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len); /** * Import an #YH_AUTHENTICATION_KEY with long lived keys derived from a password * * @param session Authenticated session to use * @param key_id Object ID of the key. 0 if the Object ID should be generated by *the device * @param label Label of the key. Maximum length is #YH_OBJ_LABEL_LEN * @param domains Domains to which the key belongs. See #yh_string_to_domains() * @param capabilities Capabilities of the key. See #yh_string_to_capabilities() * @param delegated_capabilities Delegated capabilities of the key. See *#yh_string_to_capabilities() * @param password Password used to derive the long lived encryption key and MAC *key of the Athentication Key * @param password_len Length of password * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * See #yh_rc for other possible errors * @see Authentication *Key **/ yh_rc yh_util_import_authentication_key_derived( yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, const yh_capabilities *delegated_capabilities, const uint8_t *password, size_t password_len); /** * Replace the long lived encryption key and MAC key associated with an *#YH_AUTHENTICATION_KEY in the device * * @param session Authenticated session to use * @param key_id Object ID of the key to replace * @param key_enc New long lived encryption key * @param key_enc_len Length of the new encryption key. Must be #YH_KEY_LEN * @param key_mac New long lived MAC key * @param key_mac_len Length of the new MAC key. Must be #YH_KEY_LEN * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL or if *key_enc_len or key_mac_len are not the expected values. * See #yh_rc for other possible errors * * @see Authentication *Key **/ yh_rc yh_util_change_authentication_key(yh_session *session, uint16_t *key_id, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len); /** * Replace the long lived encryption key and MAC key associated with an *#YH_AUTHENTICATION_KEY in the device with keys derived from a password * * @param session Authenticated session to use * @param key_id Object ID of the key to replace * @param password Password to derive the new encryption key and MAC key * @param password_len Length of password * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * See #yh_rc for other possible errors * * @see Authentication *Key * **/ yh_rc yh_util_change_authentication_key_derived(yh_session *session, uint16_t *key_id, const uint8_t *password, size_t password_len); /** * Get a #YH_TEMPLATE object from the device * * @param session Authenticated session to use * @param object_id Object ID of the Template to get * @param out The retrieved Template * @param out_len Length of the retrieved Template * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * See #yh_rc for other possible errors **/ yh_rc yh_util_get_template(yh_session *session, uint16_t object_id, uint8_t *out, size_t *out_len); /** * Import a #YH_TEMPLATE object into the device * * @param session Authenticated session to use * @param object_id Object ID of the Template. 0 if the Object ID should be *generated by the device * @param label Label of the Template. Maximum length is #YH_OBJ_LABEL_LEN * @param domains Domains the Template will be operating within. See *#yh_string_to_domains() * @param capabilities Capabilities of the Template. See *#yh_string_to_capabilities * @param algorithm Algorithm of the Template * @param in Template to import * @param in_len Length of the Template to import * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL or if *in_len is too big. * See #yh_rc for other possible errors **/ yh_rc yh_util_import_template(yh_session *session, uint16_t *object_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const uint8_t *in, size_t in_len); /** * Create a Yubico OTP AEAD using the provided data * * @param session Authenticated session to use * @param key_id Object ID of the Otp-aead Key to use * @param key OTP key * @param private_id OTP private id * @param out The created AEAD * @param out_len Length of the created AEAD * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * See #yh_rc for other possible errors **/ yh_rc yh_util_create_otp_aead(yh_session *session, uint16_t key_id, const uint8_t *key, const uint8_t *private_id, uint8_t *out, size_t *out_len); /** * Create OTP AEAD from random data * * @param session Authenticated session to use * @param key_id Object ID of the Otp-aead Key to use * @param out The created AEAD * @param out_len Length of the created AEAD * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * See #yh_rc for other possible errors **/ yh_rc yh_util_randomize_otp_aead(yh_session *session, uint16_t key_id, uint8_t *out, size_t *out_len); /** * Decrypt a Yubico OTP and return counters and time information. * * @param session Authenticated session to use * @param key_id Object ID of the key used for decryption * @param aead AEAD as created by #yh_util_create_otp_aead() or *#yh_util_randomize_otp_aead() * @param aead_len Length of AEAD * @param otp OTP * @param useCtr OTP use counter * @param sessionCtr OTP session counter * @param tstph OTP timestamp high * @param tstpl OTP timestamp low * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * See #yh_rc for other possible errors **/ yh_rc yh_util_decrypt_otp(yh_session *session, uint16_t key_id, const uint8_t *aead, size_t aead_len, const uint8_t *otp, uint16_t *useCtr, uint8_t *sessionCtr, uint8_t *tstph, uint16_t *tstpl); /** * Rewrap an OTP AEAD from one #YH_OTP_AEAD_KEY to another. * * @param session Authenticated session to use * @param id_from Object ID of the AEAD Key to wrap from. * @param id_to Object ID of the AEAD Key to wrap to. * @param aead_in AEAD to unwrap * @param in_len Length of AEAD * @param aead_out The created AEAD * @param out_len Length of output AEAD * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * See #yh_rc for other possible errors **/ yh_rc yh_util_rewrap_otp_aead(yh_session *session, uint16_t id_from, uint16_t id_to, const uint8_t *aead_in, size_t in_len, uint8_t *aead_out, size_t *out_len); /** * Import an #YH_OTP_AEAD_KEY used for Yubico OTP Decryption * * @param session Authenticated session to use * @param key_id Object ID of the AEAD Key. 0 if the Object ID should be *generated by the device * @param label Label of the AEAD Key. Maximum length is #YH_OBJ_LABEL_LEN * @param domains Domains the AEAD Key will be operating within. See *#yh_string_to_domains() * @param capabilities Capabilities of the AEAD Key. See *#yh_string_to_capabilities() * @param nonce_id Nonce ID * @param in AEAD Key to import * @param in_len Length of AEAD Key to import. Must be 16, 24 or 32 * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL or if *in_len is not one of 16, 24 or 32. * See #yh_rc for other possible errors **/ yh_rc yh_util_import_otp_aead_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, uint32_t nonce_id, const uint8_t *in, size_t in_len); /** * Generate an #YH_OTP_AEAD_KEY for Yubico OTP decryption in the device. * * @param session Authenticated session to use * @param key_id Object ID of the AEAD Key. 0 if the Object ID should be *generated by the device * @param label Label of the AEAD Key. Maximum length is #YH_OBJ_LABEL_LEN * @param domains Domains the AEAD Key will be operating within. See *#yh_string_to_domains() * @param capabilities Capabilities of the AEAD Key. See *#yh_string_to_capabilities() * @param algorithm Algorithm used to generate the AEAD Key. Supported *algorithms: #YH_ALGO_AES128_YUBICO_OTP, #YH_ALGO_AES192_YUBICO_OTP and *#YH_ALGO_AES256_YUBICO_OTP * @param nonce_id Nonce ID * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * See #yh_rc for other possible errors **/ yh_rc yh_util_generate_otp_aead_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, uint32_t nonce_id); /** * Get attestation of an Asymmetric Key in the form of an X.509 certificate * * @param session Authenticated session to use * @param key_id Object ID of the Asymmetric Key to attest * @param attest_id Object ID for the key used to sign the attestation *certificate * @param out The attestation certificate * @param out_len Length of the attestation certificate * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * See #yh_rc for other possible errors **/ yh_rc yh_util_sign_attestation_certificate(yh_session *session, uint16_t key_id, uint16_t attest_id, uint8_t *out, size_t *out_len); /** * Set a device-global option * * @param session Authenticated session to use * @param option Option to set. See #yh_option * @param len Length of option value * @param val Option value * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if session or val are NULL *or if len is too long. * See #yh_rc for other possible errors **/ yh_rc yh_util_set_option(yh_session *session, yh_option option, size_t len, uint8_t *val); /** * Get a device-global option * * @param session Authenticated session to use * @param option Option to get. See #yh_option * @param out Option value * @param out_len Length of option value * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * See #yh_rc for other possible errors **/ yh_rc yh_util_get_option(yh_session *session, yh_option option, uint8_t *out, size_t *out_len); /** * Report currently free storage. This is reported as free records, free pages *and page size. * * @param session Authenticated session to use * @param total_records Total number of records * @param free_records Number of free records * @param total_pages Total number of pages * @param free_pages Number of free pages * @param page_size Page size in bytes * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if the session is NULL. * See #yh_rc for other possible errors **/ yh_rc yh_util_get_storage_info(yh_session *session, uint16_t *total_records, uint16_t *free_records, uint16_t *total_pages, uint16_t *free_pages, uint16_t *page_size); /** * Encrypt (wrap) data using a #YH_WRAP_KEY. * * @param session Authenticated session to use * @param key_id Object ID of the Wrap Key to use * @param in Data to wrap * @param in_len Length of data to wrap * @param out Wrapped data * @param out_len Length of the wrapped data * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL or if *in_len is too big. * See #yh_rc for other possible errors **/ yh_rc yh_util_wrap_data(yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len); /** * Decrypt (unwrap) data using a #YH_WRAP_KEY. * * @param session Authenticated session to use * @param key_id Object ID of the Wrap Key to use * @param in Wrapped data * @param in_len Length of wrapped data * @param out Unwrapped data * @param out_len Length of unwrapped data * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL or if *in_len is too big. * See #yh_rc for other possible errors **/ yh_rc yh_util_unwrap_data(yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len); /** * Encrypt data using a AES #YH_SYMMETRIC_KEY in ECB mode * * @param session Authenticated session to use * @param key_id Object ID of the Symmetric Key to use * @param in Plaintext data * @param in_len Length of plaintext data * @param out Encrypted data * @param out_len Length of encrypted data * * @return #YHR_SUCCESS if successful. See #yh_rc for possible errors. **/ yh_rc yh_util_encrypt_aes_ecb(yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len); /** * Decrypt data using a AES #YH_SYMMETRIC_KEY in ECB mode * * @param session Authenticated session to use * @param key_id Object ID of the Symmetric Key to use * @param in Encrypted data * @param in_len Length of encrypted data * @param out Decrypted data * @param out_len Length of decrypted data * * @return #YHR_SUCCESS if successful. See #yh_rc for possible errors. **/ yh_rc yh_util_decrypt_aes_ecb(yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len); /** * Encrypt data using an AES #YH_SYMMETRIC_KEY in CBC mode * * @param session Authenticated session to use * @param key_id Object ID of the Symmetric Key to use * @param iv The 16-byte initialization vector * @param in Plaintext data * @param in_len Length of plaintext data * @param out Encrypted data * @param out_len Length of encrypted data * * @return #YHR_SUCCESS if successful. See #yh_rc for possible errors. **/ yh_rc yh_util_encrypt_aes_cbc(yh_session *session, uint16_t key_id, const uint8_t iv[16], const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len); /** * Decrypt data using an AES #YH_SYMMETRIC_KEY in CBC mode * * @param session Authenticated session to use * @param key_id Object ID of the Symmetric Key to use * @param iv The 16-byte initialization vector * @param in Encrypted data * @param in_len Length of encrypted data * @param out Decrypted data * @param out_len Length of decrypted data * * @return #YHR_SUCCESS if successful. See #yh_rc for possible errors. **/ yh_rc yh_util_decrypt_aes_cbc(yh_session *session, uint16_t key_id, const uint8_t iv[16], const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len); /** * Pad data using PKCS #7 padding * * @param buffer Data to be padded * @param length Pointer to the current length of the data * @param size The maximum size of the buffer * @param block_size The block size of the cipher used for encryption, in bytes * * @return If successful, returns #YHR_SUCCESS and sets the contents of * length to the padded length of the buffer. See #yh_rc for * other possible return codes. */ yh_rc yh_util_pad_pkcs7(uint8_t *buffer, size_t *length, size_t size, uint8_t block_size); /** * Unpad data that has PKCS #7 padding * * @warning Unpadding unauthenticated ciphertext provides a padding oracle. * * @param buffer Data to be unpadded * @param length Pointer to the current length of the data * @param block_size The block size of the cipher used for encryption, in bytes * * @return If successful, returns #YHR_SUCCESS and sets the contents of * length to the unpadded length of the buffer. See #yh_rc for * other possible return codes. */ yh_rc yh_util_unpad_pkcs7(uint8_t *buffer, size_t *length, uint8_t block_size); /** * Blink the LED of the device to identify it * * @param session Authenticated session to use * @param seconds Number of seconds to blink * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if the session is NULL. * See #yh_rc for other possible errors **/ yh_rc yh_util_blink_device(yh_session *session, uint8_t seconds); /** * Factory reset the device. Resets and reboots the device, deletes all Objects *and restores the default #YH_AUTHENTICATION_KEY. * * @param session Authenticated session to use * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if the session is NULL. * See #yh_rc for other possible errors **/ yh_rc yh_util_reset_device(yh_session *session); /** * Get the session ID * * @param session Authenticated session to use * @param sid Session ID * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. **/ yh_rc yh_get_session_id(yh_session *session, uint8_t *sid); /** * Check if the connector has a device connected * * @param connector Connector currently in use * * @return True if the connector is not NULL and there is a device connected to *it. False otherwise **/ bool yh_connector_has_device(yh_connector *connector); /** * Get the connector version * * @param connector Connector currently in use * @param major Connector major version * @param minor Connector minor version * @param patch Connector patch version * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. **/ yh_rc yh_get_connector_version(yh_connector *connector, uint8_t *major, uint8_t *minor, uint8_t *patch); /** * Get connector address * * @param connector Connector currently in use * @param address Pointer to the connector address as string * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. **/ yh_rc yh_get_connector_address(yh_connector *connector, char **const address); /** * Convert capability string to byte array * * @param capability String of capabilities separated by ',', ':' or '|' * @param result Array of #yh_capabilities * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * #YHR_BUFFER_TOO_SMALL if capability is too big * * @par Examples: * * * "get-opaque" => {"\x00\x00\x00\x00\x00\x00\x00\x01"} * * "sign-hmac:verify-hmac|exportable-under-wrap," => *{"\x00\x00\x00\x00\x00\xc1\x00\x00"} * * ",,unwrap-data|:wrap-data,,," => {"\x00\x00\x00\x60\x00\x00\x00\x00"} * * "0x7fffffffffffffff" => {"\x7f\xff\xff\xff\xff\xff\xff\xff"} * * "0xffffffffffffffff" => {"\xff\xff\xff\xff\xff\xff\xff\xff"} * * @see Capability **/ yh_rc yh_string_to_capabilities(const char *capability, yh_capabilities *result); /** * Convert an array of #yh_capabilities into strings separated by ',' * * @param num Array of #yh_capabilities * @param result Array of the capabilies as strings * @param n_result Number of elements in result * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * #YHR_BUFFER_TOO_SMALL if n_result is too small * * @see Capability **/ yh_rc yh_capabilities_to_strings(const yh_capabilities *num, const char *result[], size_t *n_result); /** * Check if a capability is set * * @param capabilities Array of #yh_capabilities * @param capability Capability to check as a string. * * @return True if the capability is in capabilities. False *otherwise * * @par Code sample * * char *capabilities_str = "sign-pkcs,decrypt-pkcs,set-option"; * yh_capabilities capabilities = {{0}}; * yh_string_to_capabilities(capabilities_str, &capabilities); * //yh_check_capability(&capabilities, "something") => false * //yh_check_capability(&capabilities, "sign-pss") => false * //yh_check_capability(&capabilities, "decrypt-pkcs") => true * * @see Capability **/ bool yh_check_capability(const yh_capabilities *capabilities, const char *capability); /** * Merge two sets of capabilities. The resulting set of capabilities contain all *capabilities from both arrays * * @param a Array of #yh_capabilities * @param b Array of #yh_capabilities * @param result Resulting array of #yh_capabilities * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * * @see Capability **/ yh_rc yh_merge_capabilities(const yh_capabilities *a, const yh_capabilities *b, yh_capabilities *result); /** * Filter one set of capabilities with another. The resulting set of *capabilities contains only the capabilities that exist in both sets of input *capabilities * * @param capabilities Array of #yh_capabilities * @param filter Array of #yh_capabilities * @param result Resulting array of #yh_capabilities * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL. * * @see Capability **/ yh_rc yh_filter_capabilities(const yh_capabilities *capabilities, const yh_capabilities *filter, yh_capabilities *result); /** * Check if an algorithm is a supported Symmetric Key AES algorithm. * * Supported AES algorithms: #YH_ALGO_AES128, #YH_ALGO_AES192 and *#YH_ALGO_AES256 * * @param algorithm Algorithm to check. See #yh_algorithm * * @return True if the algorithm is one of the supported AES algorithms. False *otherwise **/ bool yh_is_aes(yh_algorithm algorithm); /** * Check if an algorithm is a supported RSA algorithm. * * Supported RSA algorithms: #YH_ALGO_RSA_2048, #YH_ALGO_RSA_3072 and *#YH_ALGO_RSA_4096 * * @param algorithm Algorithm to check. See #yh_algorithm * * @return True if the algorithm is one of the supported RSA algorithms . False *otherwise **/ bool yh_is_rsa(yh_algorithm algorithm); /** * Check if an algorithm is a supported Elliptic Curve algorithm. * * Supported EC algorithms: #YH_ALGO_EC_P224, #YH_ALGO_EC_P256, *#YH_ALGO_EC_P384, #YH_ALGO_EC_P521, #YH_ALGO_EC_K256, #YH_ALGO_EC_BP256, *#YH_ALGO_EC_BP384 and #YH_ALGO_EC_BP512 * * @param algorithm Algorithm to check. See #yh_algorithm * * @return True if the algorithm is one of the supported EC algorithms. False *otherwise **/ bool yh_is_ec(yh_algorithm algorithm); /** * Check if an algorithm is a supported ED algorithm. * * Supported ED algorithms: #YH_ALGO_EC_ED25519 * * @param algorithm algorithm. See #yh_algorithm * * @return True if the algorithm is #YH_ALGO_EC_ED25519. False otherwise **/ bool yh_is_ed(yh_algorithm algorithm); /** * Check if algorithm is a supported HMAC algorithm. * * Supported HMAC algorithms: #YH_ALGO_HMAC_SHA1, #YH_ALGO_HMAC_SHA256, *#YH_ALGO_HMAC_SHA384 and #YH_ALGO_HMAC_SHA512 * * @param algorithm Algorithm to check. See #yh_algorithm * * @return True if the algorithm is one of the supported HMAC algorithms. False *otherwise **/ bool yh_is_hmac(yh_algorithm algorithm); /** * Get the expected key length of a key generated by the given algorithm * * @param algorithm Algorithm to check. See #yh_algorithm * @param result Expected bitlength of a key generated by the algorithm * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if result is NULL or if the *algorithm is no supported by YubiHSM 2. For a list of supported algorithms, *see #yh_algorithm **/ yh_rc yh_get_key_bitlength(yh_algorithm algorithm, size_t *result); /** * Convert an algorithm to its string representation. * * @param algo Algorithm to convert. See #yh_algorithm * @param result The algorithm as a String. "Unknown" if the algorithm is not *supported by YubiHSM 2. * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if result is NULL. * * @see Algorithms **/ yh_rc yh_algo_to_string(yh_algorithm algo, char const **result); /** * Convert a string to an algorithm's numeric value * * @param string Algorithm as string. See #yh_algorithm * @param algo Algorithm numeric value * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL or if the *algorithm is not supported by YubiHSM 2. * * @par Code sample * * yh_algorithm algorithm; * //yh_string_to_algo(NULL, &algorithm) => YHR_INVALID_PARAMETERS * //yh_string_to_algo("something", NULL) => YHR_INVALID_PARAMETERS * //yh_string_to_algo("something", &algorithm) => YHR_INVALID_PARAMETERS * //yh_string_to_algo("rsa-pkcs1-sha1", &algorithm) => *YH_ALGO_RSA_PKCS1_SHA1 * //yh_string_to_algo("rsa2048", &algorithm) => YH_ALGO_RSA_2048 * * @see Algorithms **/ yh_rc yh_string_to_algo(const char *string, yh_algorithm *algo); /** * Convert a #yh_object_type to its string representation * * @param type Type to convert. See #yh_object_type * @param result The type as a String. "Unknown" if the type was not recognized * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if result is NULL. * * @par Code sample * * const char *string; * //yh_type_to_string(0, NULL) => YHR_INVALID_PARAMETERS * //yh_type_to_string(99, &string) => string="Unknown" * //yh_type_to_string(YH_OPAQUE, &string) => string="opaque" * //yh_type_to_string(YH_AUTHENTICATION_KEY, &string) => *string="authentication-key" * * @see Object **/ yh_rc yh_type_to_string(yh_object_type type, char const **result); /** * Convert a string to a type's numeric value * * @param string Type as a String. See #yh_object_type * @param type Type numeric value * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL or if the type *was not recognized. * * @par Code sample * * yh_object_type type; * //yh_string_to_type(NULL, &type) => YHR_INVALID_PARAMETERS * //yh_string_to_type("something", NULL) => YHR_INVALID_PARAMETERS * //yh_string_to_type("something", &type) => YHR_INVALID_PARAMETERS * //yh_string_to_type("opaque", &type) => type=YH_OPAQUE * //yh_string_to_type("authentication-key", &type) => *type=YH_AUTHENTICATION_KEY * * @see Object **/ yh_rc yh_string_to_type(const char *string, yh_object_type *type); /** * Convert a string to an option's numeric value * * @param string Option as string. See #yh_option * @param option Option numeric value * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL or if the option *was not recognized. * * @par Code sample * * yh_option option; * //yh_string_to_option(NULL, &option) => YHR_INVALID_PARAMETERS * //yh_string_to_option("something", NULL) => YHR_INVALID_PARAMETERS * //yh_string_to_option("something", &option) => YHR_INVALID_PARAMETERS * //yh_string_to_option("force-audit", &option) => *option=YH_OPTION_FORCE_AUDIT * * @see Options **/ yh_rc yh_string_to_option(const char *string, yh_option *option); /** * Verify an array of log entries * * @param logs Array of log entries * @param n_items number of log entries * @param last_previous_log Optional pointer to the entry before the first entry *in logs * * @return True if verification succeeds. False otherwise * * @see Logs **/ bool yh_verify_logs(yh_log_entry *logs, size_t n_items, yh_log_entry *last_previous_log); /** * Convert a string to a domain's numeric value. * * The domains string can contain one or several domains separated by ',', ':' *or *'|'. Each domain can be written in decimal or hex format * * @param domains String of domains * @param result Resulting parsed domains as an unsigned int * * @return #YHR_SUCCESS if successful. * #YHR_INVALID_PARAMETERS if input parameters are NULL, if the domains *string is does not contains the expected values * * @par Examples * * * "1" => 1 * * "1,2:3,4|5,6;7,8,9,10,11,12,13,14,15,16" => 0xffff * * "1,16" => 0x8001 * * "16" => 0x8000 * * "16,15" => 0xc000 * * "1,0xf" => 0x4001 * * "0x1,0x2" => 3 * * "0x8888" => 0x8888 * * "0" => 0 * * "all" => 0xffff * * "2" => 2 * * "2:4" => 10 * * @see Domains **/ yh_rc yh_string_to_domains(const char *domains, uint16_t *result); /** * Convert domains parameter to its String representation * * @param domains Encoded domains * @param string Domains as a string * @param max_len Maximum length of the string * * @return #YHR_SUCCESS if successful. * #YHR_BUFFER_TOO_SMALL if max_len is too small * * @par Examples * * * 1 => "1" * * 0x8001 => "1:16" * * 0, "" * * 0xffff => "1:2:3:4:5:6:7:8:9:10:11:12:13:14:15:16" * * @see Domains **/ yh_rc yh_domains_to_string(uint16_t domains, char *string, size_t max_len); #ifdef __cplusplus } #endif #ifdef _MSC_VER #pragma strict_gs_check(on) #endif #ifdef FUZZING #include yh_rc compute_cryptogram(const uint8_t *key, uint16_t key_len, uint8_t type, const uint8_t context[SCP_CONTEXT_LEN], uint16_t L, uint8_t *key_out); void increment_ctr(uint8_t *ctr, uint16_t len); #endif #endif yubihsm-shell-2.7.1/lib/data_compress.h0000644000175100017510000000254115133003406017454 0ustar runnerrunner/* * Copyright 2024 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* ** Implements platform specific operations to compress and uncompress X509Cert */ #ifndef YUBIHSM_SHELL_DATA_COMPRESS_H #define YUBIHSM_SHELL_DATA_COMPRESS_H #include "../common/platform-config.h" #include #include #ifdef __cplusplus extern "C" { #endif #ifndef __WIN32 #define YH_INTERNAL __attribute__((visibility("hidden"))) #else #define YH_INTERNAL #endif int YH_INTERNAL compress_data(const uint8_t *data, size_t data_len, uint8_t *compressed_data, size_t *compressed_data_len); int YH_INTERNAL decompress_data(uint8_t *compressed_data, size_t compressed_data_len, uint8_t *data, size_t *data_len); #endif // YUBIHSM_SHELL_DATA_COMPRESS_H yubihsm-shell-2.7.1/lib/error.c0000644000175100017510000000600615133003406015754 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #define ERR(name, desc) \ { name, desc } typedef struct { yh_rc rc; const char *description; } err_t; static const err_t errors[] = { ERR(YHR_SUCCESS, "Success"), ERR(YHR_MEMORY_ERROR, "Unable to allocate memory"), ERR(YHR_INIT_ERROR, "Unable to initialize libyubihsm"), ERR(YHR_CONNECTION_ERROR, "Connection error"), ERR(YHR_CONNECTOR_NOT_FOUND, "Unable to find a suitable connector"), ERR(YHR_INVALID_PARAMETERS, "Invalid argument to a function"), ERR(YHR_WRONG_LENGTH, "Mismatch between expected and received length"), ERR(YHR_BUFFER_TOO_SMALL, "Not enough space to store data"), ERR(YHR_CRYPTOGRAM_MISMATCH, "Unable to verify cryptogram"), ERR(YHR_SESSION_AUTHENTICATION_FAILED, "Unable to authenticate session"), ERR(YHR_MAC_MISMATCH, "Unable to verify MAC"), ERR(YHR_DEVICE_OK, "No error"), ERR(YHR_DEVICE_INVALID_COMMAND, "Unrecognized command"), ERR(YHR_DEVICE_INVALID_DATA, "Malformed command / invalid data"), ERR(YHR_DEVICE_INVALID_SESSION, "Invalid session"), ERR(YHR_DEVICE_AUTHENTICATION_FAILED, "Message encryption / verification failed"), ERR(YHR_DEVICE_SESSIONS_FULL, "All sessions are allocated"), ERR(YHR_DEVICE_SESSION_FAILED, "Session creation failed"), ERR(YHR_DEVICE_STORAGE_FAILED, "Storage failure"), ERR(YHR_DEVICE_WRONG_LENGTH, "Wrong length"), ERR(YHR_DEVICE_INSUFFICIENT_PERMISSIONS, "Wrong permissions for operation"), ERR(YHR_DEVICE_LOG_FULL, "Log buffer is full and forced audit is set"), ERR(YHR_DEVICE_OBJECT_NOT_FOUND, "Object not found"), ERR(YHR_DEVICE_INVALID_ID, "Invalid ID used"), ERR(YHR_DEVICE_INVALID_OTP, "Invalid OTP"), ERR(YHR_DEVICE_DEMO_MODE, "Demo mode, power cycle device"), ERR(YHR_DEVICE_COMMAND_UNEXECUTED, "The command execution has not terminated"), ERR(YHR_GENERIC_ERROR, "Generic error"), ERR(YHR_DEVICE_OBJECT_EXISTS, "An Object with that ID already exists"), ERR(YHR_CONNECTOR_ERROR, "Connector operation failed"), ERR(YHR_DEVICE_SSH_CA_CONSTRAINT_VIOLATION, "SSH CA constraint violation"), ERR(YHR_DEVICE_ALGORITHM_DISABLED, "Algorithm disabled"), }; const char *yh_strerror(yh_rc err) { static const char *unknown = "Unknown yubihsm error"; const char *p; if (-err < 0 || -err >= (int) (sizeof(errors) / sizeof(errors[0]))) { return unknown; } p = errors[-err].description; if (!p) { p = unknown; } return p; } yubihsm-shell-2.7.1/lib/data_compress.c0000644000175100017510000000527515133003406017456 0ustar runnerrunner/* * Copyright 2024 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include "data_compress.h" #include "debug_lib.h" int compress_data(const uint8_t *data, size_t data_len, uint8_t *compressed_data, size_t *compressed_data_len) { z_stream zs = {0}; zs.zalloc = Z_NULL; zs.zfree = Z_NULL; zs.opaque = Z_NULL; zs.avail_in = (uInt) data_len; zs.next_in = (Bytef *) data; zs.avail_out = (uInt) *compressed_data_len; zs.next_out = (Bytef *) compressed_data; int res = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS | 16, 8, Z_DEFAULT_STRATEGY); if (res != Z_OK) { DBG_ERR("Failed to initialize data compression. ZLIB error code: %d (%s)", res, zError(res)); return -1; } res = deflate(&zs, Z_FINISH); if (res != Z_STREAM_END) { DBG_ERR("Failed to compress data. ZLIB error code: %d (%s)", res, zError(res)); return -1; } res = deflateEnd(&zs); if (res != Z_OK) { DBG_ERR("Failed to finish data compression. ZLIB error code: %d (%s)", res, zError(res)); return -1; } *compressed_data_len = zs.total_out; return 0; } int decompress_data(uint8_t *compressed_data, size_t compressed_data_len, uint8_t *data, size_t *data_len) { uint8_t *dataptr = compressed_data; z_stream zs = {0}; zs.zalloc = Z_NULL; zs.zfree = Z_NULL; zs.opaque = Z_NULL; zs.avail_in = (uInt) compressed_data_len; zs.next_in = (Bytef *) dataptr; zs.avail_out = (uInt) *data_len; zs.next_out = (Bytef *) data; int res = inflateInit2(&zs, MAX_WBITS | 16); if (res != Z_OK) { DBG_ERR("Failed to initialize data decompression. ZLIB error code: %d (%s)", res, zError(res)); return -1; } res = inflate(&zs, Z_FINISH); if (res != Z_STREAM_END) { DBG_ERR("Failed to decompress data. ZLIB error code: %d (%s)", res, zError(res)); return -1; } res = inflateEnd(&zs); if (res != Z_OK) { DBG_ERR("Failed to finish data decompression. ZLIB error code: %d (%s)", res, zError(res)); return -1; } *data_len = zs.total_out; return 0; } yubihsm-shell-2.7.1/lib/scp.h0000644000175100017510000000357515133003406015425 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SCP_H #define SCP_H #include #include // Data derivation constants #define SCP_CARD_CRYPTOGRAM 0x00 #define SCP_HOST_CRYPTOGRAM 0x01 #define SCP_CARD_CHALLENGE 0x02 #define SCP_S_ENC_DERIVATION 0x04 #define SCP_S_MAC_DERIVATION 0x06 #define SCP_S_RMAC_DERIVATION 0x07 // Lengths #define AES_128_KEY_LEN 16 #define AES_192_KEY_LEN 24 #define AES_256_KEY_LEN 32 #define SCP_KEY_LEN (AES_128_KEY_LEN) #define SCP_PRF_LEN 16 // One AES block #define SCP_CARD_CHAL_LEN 8 #define SCP_HOST_CHAL_LEN 8 #define SCP_CARD_CRYPTO_LEN 8 #define SCP_HOST_CRYPTO_LEN 8 #define SCP_MAC_LEN 8 #define SCP_CONTEXT_LEN 16 #define SCP_AUTHKEY_ID_LEN 2 #ifndef FUZZING #define SCP_MSG_BUF_SIZE 3136 #else // in fuzzing builds make the data buffers smaller #define SCP_MSG_BUF_SIZE 100 #endif // Message #pragma pack(push, 1) union _Msg { struct { uint8_t cmd; uint16_t len; uint8_t data[SCP_MSG_BUF_SIZE]; } st; uint8_t raw[SCP_MSG_BUF_SIZE + 3]; }; #pragma pack(pop) typedef union _Msg Msg; struct yh_connector; typedef struct { uint8_t sid; uint8_t s_enc[SCP_KEY_LEN]; uint8_t s_mac[SCP_KEY_LEN]; uint8_t s_rmac[SCP_KEY_LEN]; uint8_t mac_chaining_value[SCP_PRF_LEN]; uint8_t ctr[SCP_PRF_LEN]; char identifier[17]; struct yh_connector *parent; } Scp_ctx; #endif yubihsm-shell-2.7.1/lib/yubihsm.pc.in0000644000175100017510000000040315133003406017063 0ustar runnerrunnerlibdir=-L@YUBIHSM_INSTALL_LIB_DIR@ includedir=-I@YUBIHSM_INSTALL_INC_DIR@ Name: yubihsm Description: Yubico YubiHSM C Library URL: https://www.yubico.com/ Version: @VERSION@ Requires.private: libcrypto libcurl Libs: ${libdir} -lyubihsm Cflags: ${includedir} yubihsm-shell-2.7.1/lib/README.adoc0000644000175100017510000000175115133003406016246 0ustar runnerrunner== YubiHSM Library The YubiHSM C Library `libyubihsm` is a native library to interact with a YubiHSM 2 device. Two main sets of functions are exposed. Functions prefixed with only `yh_` are low-level functions (e.g., send byte array to the device) that perform a simple single action and can be used to build more advanced functionalities. Functions prefixed with `yh_util_` are higher-level function that perform multiple actions together (e.g. sign the content of a buffer with a specific padding scheme). === Documentation The library is annotated with Doxygen comments and a `Doxyfile` is provided. To build the library simply run [source, bash] ---- $ cd lib $ doxygen ---- and open the `doxygen/html/index.html` file with your preferred browser. A pre-built version of the documentation is available link:https://developers.yubico.com/YubiHSM2/Releases/libyubihsm-doxygen-1.0.0.tar.gz[here]. === Examples Code examples of how to use the library are available in the examples directory. yubihsm-shell-2.7.1/lib/version.rc.in0000644000175100017510000000215615133003406017101 0ustar runnerrunner #include #define VER_FILEVERSION @yubihsm_shell_VERSION_MAJOR@,@yubihsm_shell_VERSION_MINOR@,@yubihsm_shell_VERSION_PATCH@,0 #define VER_FILEVERSION_STR "@yubihsm_shell_VERSION_MAJOR@.@yubihsm_shell_VERSION_MINOR@.@yubihsm_shell_VERSION_PATCH@.0" VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION PRODUCTVERSION VER_FILEVERSION FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x40004L FILETYPE 0x2L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Yubico AB" VALUE "FileDescription", "YubiHSM Interface Library" VALUE "FileVersion", VER_FILEVERSION_STR VALUE "InternalName", "libyubihsm.dll" VALUE "LegalCopyright", "\xa9 Yubico AB" VALUE "OriginalFilename", "libyubihsm.dll" VALUE "ProductName", "YubiHSM" VALUE "ProductVersion", VER_FILEVERSION_STR END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END yubihsm-shell-2.7.1/lib/yubihsm_usb.c0000644000175100017510000000770215133003406017160 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "../common/platform-config.h" #ifdef __WIN32 #include #else #include #endif #include "yubihsm.h" #include "internal.h" #include "yubihsm_usb.h" #include "debug_lib.h" #define UNUSED(x) (void) (x) #ifndef STATIC uint8_t YH_INTERNAL _yh_verbosity; FILE YH_INTERNAL *_yh_output; #endif static void backend_set_verbosity(uint8_t verbosity, FILE *output) { _yh_verbosity = verbosity; _yh_output = output; } static yh_rc backend_init(uint8_t verbosity, FILE *output) { DBG_INFO("backend_init"); backend_set_verbosity(verbosity, output); return YHR_SUCCESS; } static yh_rc backend_connect(yh_connector *connector, int timeout) { DBG_INFO("backend_connect"); unsigned long serial = 0; yh_rc ret = YHR_CONNECTOR_ERROR; yh_backend *backend = NULL; UNUSED(timeout); if (parse_usb_url(connector->api_url, &serial) == false) { DBG_ERR("Failed to parse URL: '%s'", connector->api_url); goto out; } backend = connector->connection; usb_set_serial(backend, serial); if (usb_open_device(backend) == false) { DBG_ERR("No device returned"); goto out; } ret = YHR_SUCCESS; connector->has_device = 1; out: return ret; } static void backend_disconnect(yh_backend *connection) { DBG_INFO("backend_disconnect"); usb_destroy(&connection); } static yh_rc backend_send_msg(yh_backend *connection, Msg *msg, Msg *response, const char *identifier) { int32_t trf_len = ntohs(msg->st.len) + 3; yh_rc ret = YHR_GENERIC_ERROR; unsigned long read_len = 0; UNUSED(identifier); for (int i = 0; i <= 1; i++) { if (ret != YHR_GENERIC_ERROR) { DBG_INFO("Reconnecting device"); usb_close(connection); if (usb_open_device(connection) == false) { DBG_ERR("Failed reconnecting device"); return YHR_CONNECTOR_ERROR; } } if (usb_write(connection, msg->raw, trf_len) == 0) { ret = YHR_CONNECTOR_ERROR; DBG_ERR("USB write failed"); continue; } read_len = sizeof(response->raw); if (usb_read(connection, response->raw, &read_len) == 0) { ret = YHR_CONNECTOR_ERROR; DBG_ERR("USB read failed"); continue; } ret = YHR_SUCCESS; break; } if (ret != YHR_SUCCESS) { return ret; } if (read_len < 3) { DBG_ERR("Not enough data received; %lu", read_len); return YHR_WRONG_LENGTH; } if (ntohs(response->st.len) != read_len - 3) { DBG_ERR("Wrong length received, %d vs %lu", ntohs(response->st.len), read_len); return YHR_WRONG_LENGTH; } return YHR_SUCCESS; } static void backend_cleanup(void) { DBG_INFO("backend_cleanup"); } static yh_rc backend_option(yh_backend *connection, yh_connector_option opt, const void *val) { UNUSED(connection); UNUSED(opt); UNUSED(val); DBG_ERR("Backend options not (yet?) supported for USB"); return YHR_CONNECTOR_ERROR; } static struct backend_functions f = {backend_init, backend_create, backend_connect, backend_disconnect, backend_send_msg, backend_cleanup, backend_option, backend_set_verbosity}; #ifdef STATIC struct backend_functions *usb_backend_functions(void) { #else struct backend_functions *backend_functions(void) { #endif return &f; } yubihsm-shell-2.7.1/lib/yubihsm_usb.h0000644000175100017510000000234115133003406017157 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef YUBIHSM_USB_H #define YUBIHSM_USB_H #ifndef __WIN32 #define YH_INTERNAL __attribute__((visibility("hidden"))) #else #define YH_INTERNAL #endif void YH_INTERNAL usb_close(yh_backend *state); void YH_INTERNAL usb_destroy(yh_backend **state); yh_backend YH_INTERNAL *backend_create(void); bool YH_INTERNAL usb_open_device(yh_backend *backend); int YH_INTERNAL usb_write(yh_backend *state, unsigned char *buf, long unsigned len); int YH_INTERNAL usb_read(yh_backend *state, unsigned char *buf, long unsigned *len); void YH_INTERNAL usb_set_serial(yh_backend *state, unsigned long serial); #endif yubihsm-shell-2.7.1/lib/yubihsm_curl.c0000644000175100017510000001715115133003406017333 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include "yubihsm.h" #include "internal.h" #include "debug_lib.h" #include "curl/curl.h" struct state { CURL *curl; }; struct curl_data { uint8_t *ptr; uint8_t *end; }; #ifndef STATIC uint8_t YH_INTERNAL _yh_verbosity; FILE YH_INTERNAL *_yh_output; #endif static size_t curl_callback_write(void *ptr, size_t size, size_t nmemb, void *stream) { struct curl_data *data = (struct curl_data *) stream; // Multiply & check for overflow size_t tot = size * nmemb; if (tot < size || tot < nmemb) { return 0; } // Add & check for overflow uint8_t *new_ptr = data->ptr + tot; if (new_ptr < data->ptr || new_ptr > data->end) { return 0; } memcpy(data->ptr, ptr, tot); data->ptr = new_ptr; return tot; } static void backend_set_verbosity(uint8_t verbosity, FILE *output) { _yh_verbosity = verbosity; _yh_output = output; } static yh_rc backend_init(uint8_t verbosity, FILE *output) { DBG_INFO("backend_init"); CURLcode rc; backend_set_verbosity(verbosity, output); rc = curl_global_init( CURL_GLOBAL_DEFAULT); // NOTE(adma): this funciton is not thread safe if (rc != CURLE_OK) { DBG_ERR("%s", curl_easy_strerror(rc)); return YHR_CONNECTOR_ERROR; } return YHR_SUCCESS; } static yh_backend *backend_create(void) { DBG_INFO("backend_create"); return curl_easy_init(); } static yh_rc backend_connect(yh_connector *connector, int timeout) { DBG_INFO("backend_connect"); CURLcode rc; uint8_t scratch[257] = {0}; struct curl_data data = {scratch, scratch + sizeof(scratch) - 1}; char curl_error[CURL_ERROR_SIZE] = {0}; DBG_INFO("Trying to connect to %s", connector->status_url); curl_easy_setopt(connector->connection, CURLOPT_URL, connector->status_url); curl_easy_setopt(connector->connection, CURLOPT_CONNECTTIMEOUT, timeout); #ifdef CURLOPT_TCP_KEEPALIVE curl_easy_setopt(connector->connection, CURLOPT_TCP_KEEPALIVE, 1); #endif /* CURLOPT_TCP_KEEPALIVE */ curl_easy_setopt(connector->connection, CURLOPT_FAILONERROR, 1); curl_easy_setopt(connector->connection, CURLOPT_USERAGENT, "YubiHSM curl/" VERSION); curl_easy_setopt(connector->connection, CURLOPT_WRITEFUNCTION, curl_callback_write); curl_easy_setopt(connector->connection, CURLOPT_ERRORBUFFER, curl_error); curl_easy_setopt(connector->connection, CURLOPT_WRITEDATA, &data); rc = curl_easy_perform(connector->connection); if (rc != CURLE_OK) { if (strlen(curl_error) > 0) { DBG_ERR("Failure when connecting: '%s'", curl_error); } else { DBG_ERR("Failure when connecting: '%s'", curl_easy_strerror(rc)); } return YHR_CONNECTOR_NOT_FOUND; } size_t size = data.ptr - scratch; size_t len = strlen((char *) scratch); if (len != size) { DBG_ERR("Amount of data received does not match scratch buffer. Expected " "%zu, found %zu", len, size); return YHR_GENERIC_ERROR; } parse_status_data((char *) scratch, connector); if (!connector->has_device) { DBG_ERR("Failure when connecting: Connector has no device"); return YHR_CONNECTOR_NOT_FOUND; } DBG_INFO("Found working connector"); curl_easy_setopt(connector->connection, CURLOPT_URL, connector->api_url); return YHR_SUCCESS; } static void backend_disconnect(yh_backend *connection) { DBG_INFO("backend_disconnect"); curl_easy_cleanup(connection); } static yh_rc backend_send_msg(yh_backend *connection, Msg *msg, Msg *response, const char *identifier) { CURLcode rc; int32_t trf_len = ntohs(msg->st.len) + 3; struct curl_data data = {response->raw, response->raw + sizeof(response->raw)}; struct curl_slist *headers = NULL; char curl_error[CURL_ERROR_SIZE] = {0}; char hsm_identifier[64]; headers = curl_slist_append(NULL, "Content-Type: application/octet-stream"); if (identifier != NULL && strlen(identifier) > 0 && strlen(identifier) < 32) { snprintf(hsm_identifier, 64, "YubiHSM-Session: %s", identifier); headers = curl_slist_append(headers, hsm_identifier); } curl_easy_setopt(connection, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(connection, CURLOPT_POSTFIELDS, (void *) msg->raw); curl_easy_setopt(connection, CURLOPT_POSTFIELDSIZE, trf_len); curl_easy_setopt(connection, CURLOPT_WRITEDATA, &data); curl_easy_setopt(connection, CURLOPT_ERRORBUFFER, curl_error); // NOTE(adma): connection is actually established here the first time rc = curl_easy_perform(connection); curl_slist_free_all(headers); if (rc != CURLE_OK) { goto sm_failure; } size_t size = data.ptr - response->raw; if (size < 3) { DBG_ERR("Not enough data received: %zu", size); return YHR_WRONG_LENGTH; } if (ntohs(response->st.len) != size - 3) { DBG_ERR("Wrong length received, %d vs %zu", ntohs(response->st.len), size); return YHR_WRONG_LENGTH; } return YHR_SUCCESS; sm_failure: if (strlen(curl_error) > 0) { DBG_ERR("Curl perform failed: '%s'", curl_error); } else { DBG_ERR("Curl perform failed: '%s'", curl_easy_strerror(rc)); } return YHR_CONNECTOR_ERROR; } static void backend_cleanup(void) { DBG_INFO("backend_cleanup"); /* by all rights we should call curl_global_cleanup() here, but.. if curl is * using openssl that will cleanup all openssl context, which if we're called * through pkcs11_engine and our pkcs11 module will break everything, so we * don't. */ // curl_global_cleanup(); } static yh_rc backend_option(yh_backend *connection, yh_connector_option opt, const void *val) { CURLoption option; const char *optname; switch (opt) { case YH_CONNECTOR_HTTPS_CA: option = CURLOPT_CAINFO; optname = "CURLOPT_CAINFO"; break; case YH_CONNECTOR_HTTPS_CERT: option = CURLOPT_SSLCERT; optname = "CURLOPT_SSLCERT"; break; case YH_CONNECTOR_HTTPS_KEY: option = CURLOPT_SSLKEY; optname = "CURLOPT_SSLKEY"; break; case YH_CONNECTOR_PROXY_SERVER: option = CURLOPT_PROXY; optname = "CURLOPT_PROXY"; break; case YH_CONNECTOR_NOPROXY: option = CURLOPT_NOPROXY; optname = "CURLOPT_NOPROXY"; break; default: DBG_ERR("%d is an unknown option", opt); return YHR_INVALID_PARAMETERS; } CURLcode rc = curl_easy_setopt(connection, option, val); if (rc == CURLE_OK) { DBG_INFO("Successfully set %s.", optname); return YHR_SUCCESS; } else { DBG_ERR("Failed to set %s (%d): %s", optname, rc, curl_easy_strerror(rc)); return YHR_CONNECTOR_ERROR; } } static struct backend_functions f = {backend_init, backend_create, backend_connect, backend_disconnect, backend_send_msg, backend_cleanup, backend_option, backend_set_verbosity}; #ifdef STATIC struct backend_functions *http_backend_functions(void) { #else struct backend_functions *backend_functions(void) { #endif return &f; } yubihsm-shell-2.7.1/lib/CMakeLists.txt0000644000175100017510000002204015133003406017213 0ustar runnerrunner# # Copyright 2015-2018 Yubico AB # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # if(${WIN32_BCRYPT}) else(${WIN32_BCRYPT}) include(${CMAKE_SOURCE_DIR}/cmake/openssl.cmake) find_libcrypto() endif(${WIN32_BCRYPT}) if(MSVC) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) endif() set ( SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/../aes_cmac/aes.c ${CMAKE_CURRENT_SOURCE_DIR}/../aes_cmac/aes_cmac.c ${CMAKE_CURRENT_SOURCE_DIR}/../common/hash.c ${CMAKE_CURRENT_SOURCE_DIR}/../common/pkcs5.c ${CMAKE_CURRENT_SOURCE_DIR}/../common/rand.c ${CMAKE_CURRENT_SOURCE_DIR}/../common/ecdh.c error.c lib_util.c yubihsm.c ) if (ENABLE_CERT_COMPRESS) set(SOURCE ${SOURCE} data_compress.c) include(${CMAKE_SOURCE_DIR}/cmake/zlib.cmake) find_zlib() endif() if(MSVC) set(SOURCE ${SOURCE} ${CMAKE_CURRENT_SOURCE_DIR}/../common/time_win.c) endif(MSVC) set(STATIC_SOURCE ${SOURCE}) if(NOT ${WIN32_BCRYPT}) set(SOURCE ${SOURCE} ${CMAKE_CURRENT_SOURCE_DIR}/../common/openssl-compat.c) endif(NOT ${WIN32_BCRYPT}) set (STATIC_SOURCE ${SOURCE}) if(WIN32) set(ADDITIONAL_LIBRARY ws2_32) set ( HTTP_SOURCE yubihsm_winhttp.c lib_util.c ${CMAKE_CURRENT_BINARY_DIR}/version_winhttp.rc ${CMAKE_CURRENT_SOURCE_DIR}/../common/time_win.c ) set ( USB_SOURCE yubihsm_usb.c yubihsm_winusb.c lib_util.c ${CMAKE_CURRENT_BINARY_DIR}/version_winusb.rc ${CMAKE_CURRENT_SOURCE_DIR}/../common/time_win.c ) set(HTTP_LIBRARY winhttp ws2_32) set(USB_LIBRARY winusb ws2_32 setupapi) if(${WIN32_BCRYPT}) set (CRYPT_LIBRARY bcrypt) add_definitions (-D_WIN32_BCRYPT) else(${WIN32_BCRYPT}) set(CRYPT_LIBRARY ${LIBCRYPTO_LDFLAGS}) endif(${WIN32_BCRYPT}) list(APPEND SOURCE ${CMAKE_CURRENT_BINARY_DIR}/version.rc) list(APPEND STATIC_SOURCE yubihsm_winusb.c yubihsm_usb.c yubihsm_winhttp.c) else(WIN32) set(ADDITIONAL_LIBRARY -ldl) set ( USB_SOURCE yubihsm_usb.c yubihsm_libusb.c lib_util.c ) set ( HTTP_SOURCE yubihsm_curl.c lib_util.c ) set(HTTP_LIBRARY ${LIBCURL_LDFLAGS}) set(USB_LIBRARY ${LIBUSB_LDFLAGS}) set(CRYPT_LIBRARY ${LIBCRYPTO_LDFLAGS}) list(APPEND STATIC_SOURCE yubihsm_libusb.c yubihsm_usb.c yubihsm_curl.c) if(FUZZING) add_executable(fuzz_send_plain_msg ${SOURCE} fuzz/fuzz_send_plain_msg.cc fuzz/yubihsm_fuzz.cc) set_target_properties (fuzz_send_plain_msg PROPERTIES COMPILE_FLAGS "-DSTATIC -fsanitize=fuzzer ") set_target_properties (fuzz_send_plain_msg PROPERTIES LINK_FLAGS "-fsanitize=fuzzer ") target_link_libraries (fuzz_send_plain_msg ${LIBCRYPTO_LDFLAGS}) add_executable(fuzz_send_secure_msg ${SOURCE} fuzz/fuzz_send_secure_msg.cc fuzz/yubihsm_fuzz.cc) set_target_properties (fuzz_send_secure_msg PROPERTIES COMPILE_FLAGS "-DSTATIC -fsanitize=fuzzer ") set_target_properties (fuzz_send_secure_msg PROPERTIES LINK_FLAGS "-fsanitize=fuzzer ") target_link_libraries (fuzz_send_secure_msg ${LIBCRYPTO_LDFLAGS}) endif(FUZZING) endif(WIN32) include_directories ( ${CMAKE_CURRENT_SOURCE_DIR} ${LIBCRYPTO_INCLUDEDIR} ${LIBCURL_INCLUDEDIR} ) add_library (yubihsm SHARED ${SOURCE}) add_library (yubihsm_usb SHARED ${USB_SOURCE}) add_library (yubihsm_http SHARED ${HTTP_SOURCE}) set_target_properties(yubihsm PROPERTIES BUILD_RPATH "${CMAKE_BINARY_DIR}/lib") set_target_properties (yubihsm PROPERTIES VERSION "${yubihsm_shell_VERSION_MAJOR}.${yubihsm_shell_VERSION_MINOR}.${yubihsm_shell_VERSION_PATCH}" SOVERSION ${yubihsm_shell_VERSION_MAJOR}) set_target_properties (yubihsm_usb PROPERTIES VERSION "${yubihsm_shell_VERSION_MAJOR}.${yubihsm_shell_VERSION_MINOR}.${yubihsm_shell_VERSION_PATCH}" SOVERSION ${yubihsm_shell_VERSION_MAJOR}) set_target_properties (yubihsm_http PROPERTIES VERSION "${yubihsm_shell_VERSION_MAJOR}.${yubihsm_shell_VERSION_MINOR}.${yubihsm_shell_VERSION_PATCH}" SOVERSION ${yubihsm_shell_VERSION_MAJOR}) if(MSVC) set_target_properties(yubihsm PROPERTIES OUTPUT_NAME libyubihsm) set_target_properties(yubihsm_usb PROPERTIES OUTPUT_NAME libyubihsm_usb) set_target_properties(yubihsm_http PROPERTIES OUTPUT_NAME libyubihsm_http) else(MSVC) set_target_properties(yubihsm PROPERTIES OUTPUT_NAME yubihsm) set_target_properties(yubihsm_usb PROPERTIES OUTPUT_NAME yubihsm_usb) set_target_properties(yubihsm_http PROPERTIES OUTPUT_NAME yubihsm_http) endif(MSVC) if (ENABLE_STATIC) add_library (yubihsm_static STATIC ${STATIC_SOURCE}) set_target_properties (yubihsm_static PROPERTIES POSITION_INDEPENDENT_CODE on OUTPUT_NAME yubihsm) set_target_properties (yubihsm_static PROPERTIES COMPILE_FLAGS "-DSTATIC " ) if(MSVC) set_property(TARGET yubihsm_static PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") endif(MSVC) add_coverage (yubihsm_static) endif() if(${WIN32}) else(${WIN32}) if(${LIBUSB_VERSION} VERSION_LESS 1.0.16) set(LIBUSB_CFLAGS "${LIBUSB_CFLAGS} -DNO_LIBUSB_STRERROR") endif() set_target_properties (yubihsm_usb PROPERTIES COMPILE_FLAGS ${LIBUSB_CFLAGS}) if(ENABLE_STATIC) set_property(TARGET yubihsm_static APPEND_STRING PROPERTY COMPILE_FLAGS ${LIBUSB_CFLAGS}) endif(ENABLE_STATIC) endif(${WIN32}) add_coverage (yubihsm) add_coverage (yubihsm_usb) add_coverage (yubihsm_http) add_definitions (-DVERSION="${yubihsm_shell_VERSION_MAJOR}.${yubihsm_shell_VERSION_MINOR}.${yubihsm_shell_VERSION_PATCH}") add_definitions (-DSOVERSION="${yubihsm_shell_VERSION_MAJOR}") target_link_libraries (yubihsm ${CRYPT_LIBRARY} ${ADDITIONAL_LIBRARY} ${ZLIB_LIBS}) target_link_libraries (yubihsm_usb ${USB_LIBRARY}) target_link_libraries (yubihsm_http ${HTTP_LIBRARY}) if(ENABLE_STATIC) target_link_libraries (yubihsm_static ${CRYPT_LIBRARY} ${ADDITIONAL_LIBRARY} ${HTTP_LIBRARY} ${USB_LIBRARY} ${ZLIB_LIBS}) endif(ENABLE_STATIC) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/yubihsm.pc.in ${CMAKE_CURRENT_BINARY_DIR}/yubihsm.pc @ONLY) configure_file(${CMAKE_SOURCE_DIR}/common/platform-config.h.in ${CMAKE_SOURCE_DIR}/common/platform-config.h @ONLY) if(WIN32) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version_winhttp.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version_winhttp.rc @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version_winusb.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version_winusb.rc @ONLY) endif(WIN32) install( TARGETS yubihsm ARCHIVE DESTINATION ${YUBIHSM_INSTALL_LIB_DIR} LIBRARY DESTINATION ${YUBIHSM_INSTALL_LIB_DIR} RUNTIME DESTINATION ${YUBIHSM_INSTALL_BIN_DIR}) install( TARGETS yubihsm_usb ARCHIVE DESTINATION ${YUBIHSM_INSTALL_LIB_DIR} LIBRARY DESTINATION ${YUBIHSM_INSTALL_LIB_DIR} RUNTIME DESTINATION ${YUBIHSM_INSTALL_BIN_DIR}) install( TARGETS yubihsm_http ARCHIVE DESTINATION ${YUBIHSM_INSTALL_LIB_DIR} LIBRARY DESTINATION ${YUBIHSM_INSTALL_LIB_DIR} RUNTIME DESTINATION ${YUBIHSM_INSTALL_BIN_DIR}) install(FILES yubihsm.h DESTINATION ${YUBIHSM_INSTALL_INC_DIR}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/yubihsm.pc DESTINATION ${YUBIHSM_INSTALL_PKGCONFIG_DIR}) add_subdirectory (tests) add_test( NAME parsing COMMAND test_parsing WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/lib/tests/ ) add_test( NAME pbkdf2 COMMAND test_pbkdf2 WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/lib/tests/ ) add_test( NAME attest COMMAND attest WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/examples/ ) add_test( NAME generate_ec COMMAND generate_ec ) add_test( NAME generate_hmac COMMAND generate_hmac ) add_test( NAME import_authkey COMMAND import_authkey ) add_test( NAME import_rsa COMMAND import_rsa WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/examples/ ) add_test( NAME info COMMAND info ) add_test( NAME wrap COMMAND wrap ) add_test( NAME wrap_data COMMAND wrap_data ) add_test( NAME yubico_otp COMMAND yubico_otp ) add_test( NAME echo COMMAND echo ) add_test( NAME asym_auth COMMAND asym_auth ) add_test( NAME import_ec COMMAND import_ec WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/examples/ ) add_test( NAME generate_rsa COMMAND generate_rsa ) add_test( NAME logs COMMAND logs ) add_test( NAME ssh COMMAND ssh WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/examples/ ) add_test( NAME decrypt_rsa COMMAND decrypt_rsa WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/examples/ ) add_test( NAME decrypt_ec COMMAND decrypt_ec ) add_test( NAME import_ed COMMAND import_ed WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/examples/ ) add_test( NAME change_authkey COMMAND change_authkey ) add_test( NAME encrypt_aes COMMAND encrypt_aes WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/examples" ) set_tests_properties(encrypt_aes PROPERTIES SKIP_RETURN_CODE 64) yubihsm-shell-2.7.1/lib/yubihsm_winusb.c0000644000175100017510000002317015133003406017673 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include "yubihsm.h" #include "internal.h" #include "yubihsm_usb.h" #include "debug_lib.h" struct state { HANDLE hDevice; WINUSB_INTERFACE_HANDLE hWinUSB; unsigned long serial; }; // Device GUID {D1D3C87E-0574-4E38-8346-A56439234528} static const GUID devGUID = {0xD1D3C87E, 0x0574, 0x4E38, {0x83, 0x46, 0xA5, 0x64, 0x39, 0x23, 0x45, 0x28}}; #define PIPE_OUT 0x01 // Must match endpoint descriptor definitions #define PIPE_IN 0x81 void usb_set_serial(yh_backend *state, unsigned long serial) { state->serial = serial; } bool usb_open_device(yh_backend *backend) { BOOL bResult = TRUE; HDEVINFO hDeviceInfo; SP_DEVINFO_DATA DeviceInfoData; SP_DEVICE_INTERFACE_DATA deviceInterfaceData; PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = NULL; ULONG requiredLength = 0; DWORD index = 0; HANDLE hnd = INVALID_HANDLE_VALUE; WINUSB_INTERFACE_HANDLE wusbHnd = INVALID_HANDLE_VALUE; // Get information about all the installed devices for the specified // device interface class. hDeviceInfo = SetupDiGetClassDevs(&devGUID, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (hDeviceInfo == INVALID_HANDLE_VALUE) { DBG_ERR("SetupDiGetClassDevs failed, error=%lx\n", GetLastError()); return false; } // Enumerate all the device interfaces in the device information set. DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); for (index = 0; SetupDiEnumDeviceInfo(hDeviceInfo, index, &DeviceInfoData); index++) { deviceInterfaceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA); // Get information about the device interface. bResult = SetupDiEnumDeviceInterfaces(hDeviceInfo, &DeviceInfoData, &devGUID, 0, &deviceInterfaceData); if (!bResult) { // Check if last item if (GetLastError() == ERROR_NO_MORE_ITEMS) { DBG_ERR("No more items found"); goto out; } // Check for some other error DBG_ERR("SetupDiEnumDeviceInterfaces(1) failed, error=%lx\n", GetLastError()); goto out; } // Interface data is returned in SP_DEVICE_INTERFACE_DETAIL_DATA // which we need to allocate, so we have to call this function twice. // First to get the size so that we know how much to allocate // Second, the actual call with the allocated buffer bResult = SetupDiGetDeviceInterfaceDetail(hDeviceInfo, &deviceInterfaceData, NULL, 0, &requiredLength, NULL); if (!bResult && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) { DBG_ERR("SetupDiEnumDeviceInterfaces(2) failed, error=%lx\n", GetLastError()); goto out; } // Get the interface detailed data and allocate storage pInterfaceDetailData = malloc(requiredLength); pInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); // Now call it with the correct size and allocated buffer bResult = SetupDiGetDeviceInterfaceDetail(hDeviceInfo, &deviceInterfaceData, pInterfaceDetailData, requiredLength, NULL, &DeviceInfoData); if (!bResult) { DBG_ERR("SetupDiGetDeviceInterfaceDetail failed, error=%lx\n", GetLastError()); goto out; } hnd = CreateFile(pInterfaceDetailData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); free(pInterfaceDetailData); pInterfaceDetailData = NULL; if (hnd == INVALID_HANDLE_VALUE) { DBG_ERR("CreateFile failed, error=%lx", GetLastError()); continue; } if (!WinUsb_Initialize(hnd, &wusbHnd)) { DBG_ERR("WinUsb_Initialize failed, error=%lx", GetLastError()); goto next; } if (backend->serial != 0) { USB_DEVICE_DESCRIPTOR desc; ULONG written; unsigned char ser_num[128] = {0}; if (!WinUsb_GetDescriptor(wusbHnd, USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, (unsigned char *) &desc, sizeof(desc), &written)) { DBG_ERR("WinUsb_GetDescriptor failed, error=%lx", GetLastError()); goto next; } if (!WinUsb_GetDescriptor(wusbHnd, USB_STRING_DESCRIPTOR_TYPE, desc.iSerialNumber, 0x0409, // English (US) ser_num, sizeof(ser_num), &written)) { DBG_ERR("WinUsb_GetDescriptor failed, error=%lx", GetLastError()); goto next; } DBG_INFO("Extracted serial %ls (%lu bytes) from device desc %d", (wchar_t *) (ser_num + 2), written, desc.iSerialNumber); unsigned long devSerial = wcstoul((wchar_t *) (ser_num + 2), NULL, 10); if (devSerial != backend->serial) { DBG_INFO("Device has serial %lu, not matching searched %lu", devSerial, backend->serial); goto next; } } break; next: if (wusbHnd != INVALID_HANDLE_VALUE) { WinUsb_Free(wusbHnd); wusbHnd = INVALID_HANDLE_VALUE; } if (hnd != INVALID_HANDLE_VALUE) { CloseHandle(hnd); hnd = INVALID_HANDLE_VALUE; } continue; } if (wusbHnd != INVALID_HANDLE_VALUE) { // Make sure we get a ZLP at the end every time bResult = WinUsb_SetPipePolicy(wusbHnd, PIPE_OUT, SHORT_PACKET_TERMINATE, 1, (PVOID) "\x1"); if (!bResult) { DBG_ERR("SetPipePolicy failed"); WinUsb_Free(wusbHnd); wusbHnd = INVALID_HANDLE_VALUE; CloseHandle(hnd); hnd = INVALID_HANDLE_VALUE; goto out; } { // we set up a dummy read with a 10ms timeout here, if the timeout is too // short this times out before it has time to complete. The reason for // doing this is that there might be data left in the device buffers from // earlier transactions, this should flush it. unsigned char buf[YH_MSG_BUF_SIZE]; unsigned long transferred = 0; unsigned long timeout = 10; bResult = WinUsb_SetPipePolicy(wusbHnd, PIPE_IN, PIPE_TRANSFER_TIMEOUT, sizeof(timeout), &timeout); if (!bResult) { DBG_ERR("SetPipePolicy failed"); WinUsb_Free(wusbHnd); wusbHnd = INVALID_HANDLE_VALUE; CloseHandle(hnd); hnd = INVALID_HANDLE_VALUE; goto out; } if (WinUsb_ReadPipe(wusbHnd, PIPE_IN, buf, sizeof(buf), &transferred, 0)) { DBG_INFO("%lu bytes of stale data read", transferred); } timeout = 0; bResult = WinUsb_SetPipePolicy(wusbHnd, PIPE_IN, PIPE_TRANSFER_TIMEOUT, sizeof(timeout), &timeout); if (!bResult) { DBG_ERR("SetPipePolicy failed"); WinUsb_Free(wusbHnd); wusbHnd = INVALID_HANDLE_VALUE; CloseHandle(hnd); hnd = INVALID_HANDLE_VALUE; goto out; } } } out: backend->hDevice = hnd; backend->hWinUSB = wusbHnd; if (hDeviceInfo) { SetupDiDestroyDeviceInfoList(hDeviceInfo); } free(pInterfaceDetailData); if (wusbHnd != INVALID_HANDLE_VALUE) { return true; } else { return false; } } yh_backend *backend_create(void) { DBG_INFO("backend_create"); yh_backend *backend = calloc(1, sizeof(yh_backend)); return backend; } void usb_close(yh_backend *state) { if (state && state->hDevice != INVALID_HANDLE_VALUE) { CloseHandle(state->hDevice); state->hDevice = INVALID_HANDLE_VALUE; } if (state && state->hWinUSB != INVALID_HANDLE_VALUE) { WinUsb_Free(state->hWinUSB); state->hWinUSB = INVALID_HANDLE_VALUE; } } void usb_destroy(yh_backend **state) { if (state && *state) { usb_close(*state); free(*state); *state = NULL; } } int usb_write(yh_backend *state, unsigned char *buf, long unsigned len) { long unsigned transferred; if (state->hWinUSB == INVALID_HANDLE_VALUE) { DBG_ERR("No connected device"); return 0; } BOOL bResult = WinUsb_WritePipe(state->hWinUSB, PIPE_OUT, buf, len, &transferred, 0); if (bResult) { DBG_INFO("Written %lu bytes", transferred); } else { DBG_ERR("WinUsb_WritePipe failed, error=%lx", GetLastError()); return 0; } if (transferred != len) { DBG_ERR("Transferred did not match len of write %lu-%lu", transferred, len); return 0; } return 1; } int usb_read(yh_backend *state, unsigned char *buf, long unsigned *len) { long unsigned transferred = 0; BOOL bResult; if (state->hWinUSB == INVALID_HANDLE_VALUE) { DBG_ERR("No connected device"); return 0; } DBG_INFO("Doing usb read"); bResult = WinUsb_ReadPipe(state->hWinUSB, PIPE_IN, buf, *len, &transferred, 0); if (!bResult) { DBG_ERR("WinUsb_ReadPipe failed, error=%lx\n", GetLastError()); return 0; } DBG_INFO("Read %lu bytes", transferred); *len = transferred; return 1; } yubihsm-shell-2.7.1/lib/tests/0000755000175100017510000000000015133003406015617 5ustar runnerrunneryubihsm-shell-2.7.1/lib/tests/test_util.c0000644000175100017510000000400215133003406017773 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include #include "yubihsm.h" #include "internal.h" uint8_t _yh_verbosity; FILE *_yh_output; static void test_status(void) { struct { const char *data; yh_connector c; } tests[] = { {"status=OK\nversion=1.2.3\n", {NULL, NULL, NULL, {0}, {0}, true, 1, 2, 3, "", 0, 0, {0}}}, {"", {NULL, NULL, NULL, {0}, {0}, false, 0, 0, 0, "", 0, 0, {0}}}, {"foobar", {NULL, NULL, NULL, {0}, {0}, false, 0, 0, 0, "", 0, 0, {0}}}, {"\n\n\n\n\n\n", {NULL, NULL, NULL, {0}, {0}, false, 0, 0, 0, "", 0, 0, {0}}}, {"status=NO_DEVICE\nserial=*\nversion=1.0.2\npid=412\naddress=\nport=12345", {NULL, NULL, NULL, {0}, {0}, false, 1, 0, 2, "", 12345, 412, {0}}}, {"version=1.2", {NULL, NULL, NULL, {0}, {0}, false, 1, 2, 0, "", 0, 0, {0}}}, {"version=foobar", {NULL, NULL, NULL, {0}, {0}, false, 0, 0, 0, "", 0, 0, {0}}}, {"version=2..\nstatus=OK", {NULL, NULL, NULL, {0}, {0}, true, 2, 0, 0, "", 0, 0, {0}}}, }; for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { yh_connector c = {NULL, NULL, NULL, {0}, {0}, false, 0, 0, 0, "", 0, 0, {0}}; char *data = strdup(tests[i].data); parse_status_data(data, &c); free(data); assert(memcmp(&c, &tests[i].c, sizeof(c)) == 0); } } int main(void) { _yh_output = stderr; _yh_verbosity = 0; test_status(); return 0; } yubihsm-shell-2.7.1/lib/tests/test_pbkdf2.c0000644000175100017510000000550715133003406020201 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #ifdef NDEBUG #undef NDEBUG #endif #include #include #include "../../common/pkcs5.h" static void test_pbkdf2_vectors(void) { struct vector { const uint8_t *password; size_t password_len; const uint8_t *salt; size_t salt_len; uint64_t iterations; hash_t hash; const uint8_t *output; size_t size; } vectors[] = { {(const uint8_t *) "password", 8, (const uint8_t *) "salt", 4, 1, _SHA1, (const uint8_t *) "\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9\xb5\x24\xaf" "\x60\x12\x06\x2f\xe0\x37\xa6", 20}, {(const uint8_t *) "password", 8, (const uint8_t *) "salt", 4, 2, _SHA1, (const uint8_t *) "\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e\xd9\x2a\xce" "\x1d\x41\xf0\xd8\xde\x89\x57", 20}, {(const uint8_t *) "password", 8, (const uint8_t *) "salt", 4, 4096, _SHA1, (const uint8_t *) "\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad\x49\xd9\x26" "\xf7\x21\xd0\x65\xa4\x29\xc1", 20}, //{(const uint8_t*)"password", 8, (const uint8_t*)"salt", 4, 16777216, //_SHA1, (const // uint8_t*)"\xee\xfe\x3d\x61\xcd\x4d\xa4\xe4\xe9\x94\x5b\x3d\x6b\xa2\x15\x8c\x26\x34\xe9\x84", // 20}, {(const uint8_t *) "passwordPASSWORDpassword", 24, (const uint8_t *) "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36, 4096, _SHA1, (const uint8_t *) "\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8\xd8\x36\x62" "\xc0\xe4\x4a\x8b\x29\x1a\x96\x4c\xf2\xf0\x70\x38", 25}, {(const uint8_t *) "pass\0word", 9, (const uint8_t *) "sa\0lt", 5, 4096, _SHA1, (const uint8_t *) "\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37\xd7\xf0\x34\x25\xe0\xc3", 16}, }; for (size_t i = 0; i < sizeof(vectors) / sizeof(vectors[0]); i++) { uint8_t key[256]; bool res = pkcs5_pbkdf2_hmac(vectors[i].password, vectors[i].password_len, vectors[i].salt, vectors[i].salt_len, vectors[i].iterations, vectors[i].hash, key, vectors[i].size); assert(res == true); assert(memcmp(key, vectors[i].output, vectors[i].size) == 0); } } int main(void) { test_pbkdf2_vectors(); return 0; } yubihsm-shell-2.7.1/lib/tests/CMakeLists.txt0000644000175100017510000000307015133003406020357 0ustar runnerrunner# # Copyright 2015-2018 Yubico AB # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # if(MSVC) set(ADDITIONAL_LIBRARY ws2_32) endif(MSVC) set ( SOURCE_PARSING test_parsing.c ) set ( SOURCE_PBKDF2 test_pbkdf2.c ../../common/pkcs5.c ../../common/hash.c ) set ( SOURCE_USB_URL test_usb_url.c ../lib_util.c ) if(MSVC) set(SOURCE_USB_URL ${SOURCE_USB_URL} ../../common/time_win.c) endif(MSVC) set ( SOURCE_UTIL test_util.c ../lib_util.c ) if(MSVC) set(SOURCE_UTIL ${SOURCE_UTIL} ../../common/time_win.c) endif(MSVC) include_directories ( ${CMAKE_CURRENT_SOURCE_DIR}/../lib ) add_executable (test_parsing ${SOURCE_PARSING}) add_executable (test_pbkdf2 ${SOURCE_PBKDF2}) add_executable (test_usb_url ${SOURCE_USB_URL}) add_executable (test_util ${SOURCE_UTIL}) target_link_libraries ( test_parsing yubihsm ) target_link_libraries ( test_pbkdf2 # this doesn't really need libyubihsm, needs openssl/windows whatever yubihsm ) target_link_libraries (test_usb_url ${ADDITIONAL_LIBRARY}) target_link_libraries (test_util ${ADDITIONAL_LIBRARY}) yubihsm-shell-2.7.1/lib/tests/test_usb_url.c0000644000175100017510000000304515133003406020477 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include "yubihsm.h" #include "internal.h" uint8_t _yh_verbosity = YH_VERB_ALL; FILE *_yh_output; static void test_urls(void) { struct { const char *string; unsigned long serial; bool ret; } tests[] = { {"yhusb://serial=12345", 12345, true}, {"", 0, false}, {"yhusb://", 0, true}, {"yhusb://foo=bar&serial=1000000", 1000000, true}, {"yhusb://serial=0001234", 1234, true}, {"yhusb://serial=0x1234", 0, false}, {"yhusb://serial=FF", 0, false}, {"yhusb://serial=1234foo", 0, false}, {"yhusb://serial=", 0, false}, }; for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { unsigned long serial = 0; assert(parse_usb_url(tests[i].string, &serial) == tests[i].ret); if (tests[i].ret) { assert(serial == tests[i].serial); } } } int main(void) { _yh_output = stderr; test_urls(); return 0; } yubihsm-shell-2.7.1/lib/tests/test_parsing.c0000644000175100017510000002347415133003406020477 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "yubihsm.h" #ifdef NDEBUG #undef NDEBUG #endif #include #include #include #include static void test_domains1(void) { struct { const char *string; uint16_t domains; } tests[] = { {"1", 1}, {"1,2:3,4|5,6;7,8,9,10,11,12,13,14,15,16", 0xffff}, {"1,16", 0x8001}, {"16", 0x8000}, {"16,15", 0xc000}, {"1,0xf", 0x4001}, {"0x1,0x2", 3}, {"0x8888", 0x8888}, {"0", 0}, {"all", 0xffff}, {"2", 2}, {"2:4", 10}, }; for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { uint16_t d = 0; assert(yh_string_to_domains(tests[i].string, &d) == YHR_SUCCESS); assert(d == tests[i].domains); } } static void test_domains2(void) { struct { uint16_t domains; const char *string; } tests[] = { {1, "1"}, {0x8001, "1:16"}, {0, ""}, {0xffff, "1:2:3:4:5:6:7:8:9:10:11:12:13:14:15:16"}, }; for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { char s[256]; assert(yh_domains_to_string(tests[i].domains, s, 255) == YHR_SUCCESS); assert(strcmp(s, tests[i].string) == 0); } } static void test_capabilities1(void) { struct { const char *string; yh_capabilities capabilities; } tests[] = { {"get-opaque", {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}}, {"sign-hmac:verify-hmac|exportable-under-wrap,", {{0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00}}}, {",,unwrap-data|:wrap-data,,,", {{0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00}}}, {"0x7fffffffffffffff", {{0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}}, {"0xffffffffffffffff", {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}}, }; for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { yh_capabilities c = {{0}}; assert(yh_string_to_capabilities(tests[i].string, &c) == YHR_SUCCESS); assert(memcmp(&c, &tests[i].capabilities, sizeof(c)) == 0); } } static void test_capabilities2(void) { yh_rc yrc = YHR_GENERIC_ERROR; yh_capabilities capabilities = {{0}}; const char *capabilities_array[8]; size_t capabilities_array_len; char *capabilities_list[] = {"sign-pkcs", "decrypt-pkcs", "export-wrapped", "set-option", "get-pseudo-random", "sign-hmac", "verify-hmac", "get-log-entries"}; char capabilities_string[1024]; size_t len = 0; for (size_t i = 0; i < sizeof(capabilities_list) / sizeof(capabilities_list[0]); i++) { snprintf(capabilities_string + len, sizeof(capabilities_string) - len, "%s:", capabilities_list[i]); len += strlen(capabilities_list[i]) + 1; } capabilities_string[len - 1] = '\0'; yrc = yh_string_to_capabilities(capabilities_string, &capabilities); assert(yrc == YHR_SUCCESS); assert(yh_check_capability(&capabilities, "something") == false); assert(yh_check_capability(&capabilities, "sign-pss") == false); assert(yh_check_capability(&capabilities, "sign-pkcs") == true); assert(yh_check_capability(&capabilities, "decrypt-pkcs") == true); assert(yh_check_capability(&capabilities, "export-wrapped") == true); assert(yh_check_capability(&capabilities, "set-option") == true); assert(yh_check_capability(&capabilities, "get-pseudo-random") == true); assert(yh_check_capability(&capabilities, "sign-hmac") == true); assert(yh_check_capability(&capabilities, "verify-hmac") == true); assert(yh_check_capability(&capabilities, "get-log-entries") == true); assert(yh_check_capability(&capabilities, "verify-hmac:get-log-entries") == true); capabilities_array_len = 1; yrc = yh_capabilities_to_strings(&capabilities, capabilities_array, &capabilities_array_len); assert(yrc == YHR_BUFFER_TOO_SMALL); capabilities_array_len = sizeof(capabilities_array) / sizeof(capabilities_array[0]); yrc = yh_capabilities_to_strings(&capabilities, capabilities_array, &capabilities_array_len); assert(yrc == YHR_SUCCESS); for (size_t i = 0; i < sizeof(capabilities_list) / sizeof(capabilities_list[0]); i++) { size_t j; for (j = 0; j < capabilities_array_len; j++) { if (strcmp(capabilities_list[i], capabilities_array[j]) == 0) { break; } } assert(j < capabilities_array_len); } } static void test_capabilities3(void) { const char *cap1 = "sign-pkcs,sign-pss"; const char *cap2 = "decrypt-pkcs,decrypt-oaep"; const char *cap3 = "sign-pss,decrypt-oaep"; yh_capabilities c1 = {{0}}; yh_capabilities c2 = {{0}}; yh_capabilities c3 = {{0}}; yh_capabilities res = {{0}}; assert(yh_string_to_capabilities(cap1, &c1) == YHR_SUCCESS); assert(yh_string_to_capabilities(cap2, &c2) == YHR_SUCCESS); assert(yh_string_to_capabilities(cap3, &c3) == YHR_SUCCESS); assert(yh_merge_capabilities(&c1, &c2, &res) == YHR_SUCCESS); assert(yh_check_capability(&res, "sign-pkcs") == true); assert(yh_check_capability(&res, "sign-pss") == true); assert(yh_check_capability(&res, "decrypt-pkcs") == true); assert(yh_check_capability(&res, "decrypt-oaep") == true); assert(yh_check_capability(&res, "sign-hmac") == false); assert(yh_filter_capabilities(&res, &c3, &res) == YHR_SUCCESS); assert(yh_check_capability(&res, "sign-pkcs") == false); assert(yh_check_capability(&res, "sign-pss") == true); assert(yh_check_capability(&res, "decrypt-pkcs") == false); assert(yh_check_capability(&res, "decrypt-oaep") == true); assert(yh_check_capability(&res, "sign-hmac") == false); } static void test_algorithms(void) { yh_rc yrc; assert(yh_is_hmac(YH_ALGO_RSA_2048) == false); assert(yh_is_hmac(YH_ALGO_HMAC_SHA1) == true); assert(yh_is_hmac(YH_ALGO_HMAC_SHA256) == true); assert(yh_is_hmac(YH_ALGO_HMAC_SHA384) == true); assert(yh_is_hmac(YH_ALGO_HMAC_SHA512) == true); yh_algorithm algorithm; yrc = yh_string_to_algo(NULL, &algorithm); assert(yrc == YHR_INVALID_PARAMETERS); yrc = yh_string_to_algo("something", NULL); assert(yrc == YHR_INVALID_PARAMETERS); yrc = yh_string_to_algo("something", &algorithm); assert(yrc == YHR_INVALID_PARAMETERS); yrc = yh_string_to_algo("rsa-pkcs1-sha1", &algorithm); assert(yrc == YHR_SUCCESS && algorithm == YH_ALGO_RSA_PKCS1_SHA1); yrc = yh_string_to_algo("rsa2048", &algorithm); assert(yrc == YHR_SUCCESS && algorithm == YH_ALGO_RSA_2048); yrc = yh_string_to_algo("ecp384", &algorithm); assert(yrc == YHR_SUCCESS && algorithm == YH_ALGO_EC_P384); yrc = yh_string_to_algo("mgf1-sha512", &algorithm); assert(yrc == YHR_SUCCESS && algorithm == YH_ALGO_MGF1_SHA512); } static void test_options(void) { yh_rc yrc; yh_option option; yrc = yh_string_to_option(NULL, &option); assert(yrc == YHR_INVALID_PARAMETERS); yrc = yh_string_to_option("something", NULL); assert(yrc == YHR_INVALID_PARAMETERS); yrc = yh_string_to_option("something", &option); assert(yrc == YHR_INVALID_PARAMETERS); yrc = yh_string_to_option("force-audit", &option); assert(yrc == YHR_SUCCESS && option == YH_OPTION_FORCE_AUDIT); } static void test_types(void) { yh_rc yrc; yh_object_type type; yrc = yh_string_to_type(NULL, &type); assert(yrc == YHR_INVALID_PARAMETERS); yrc = yh_string_to_type("something", NULL); assert(yrc == YHR_INVALID_PARAMETERS); yrc = yh_string_to_type("something", &type); assert(yrc == YHR_INVALID_PARAMETERS); yrc = yh_string_to_type("opaque", &type); assert(yrc == YHR_SUCCESS && type == YH_OPAQUE); yrc = yh_string_to_type("authentication-key", &type); assert(yrc == YHR_SUCCESS && type == YH_AUTHENTICATION_KEY); yrc = yh_string_to_type("asymmetric-key", &type); assert(yrc == YHR_SUCCESS && type == YH_ASYMMETRIC_KEY); yrc = yh_string_to_type("wrap-key", &type); assert(yrc == YHR_SUCCESS && type == YH_WRAP_KEY); yrc = yh_string_to_type("hmac-key", &type); assert(yrc == YHR_SUCCESS && type == YH_HMAC_KEY); yrc = yh_string_to_type("template", &type); assert(yrc == YHR_SUCCESS && type == YH_TEMPLATE); yrc = yh_string_to_type("otp-aead-key", &type); assert(yrc == YHR_SUCCESS && type == YH_OTP_AEAD_KEY); const char *string; yrc = yh_type_to_string(0, NULL); assert(yrc == YHR_INVALID_PARAMETERS); yrc = yh_type_to_string(99, &string); assert(yrc == YHR_SUCCESS && strcmp(string, "Unknown") == 0); yrc = yh_type_to_string(YH_OPAQUE, &string); assert(yrc == YHR_SUCCESS && strcmp(string, "opaque") == 0); yrc = yh_type_to_string(YH_AUTHENTICATION_KEY, &string); assert(yrc == YHR_SUCCESS && strcmp(string, "authentication-key") == 0); yrc = yh_type_to_string(YH_ASYMMETRIC_KEY, &string); assert(yrc == YHR_SUCCESS && strcmp(string, "asymmetric-key") == 0); yrc = yh_type_to_string(YH_WRAP_KEY, &string); assert(yrc == YHR_SUCCESS && strcmp(string, "wrap-key") == 0); yrc = yh_type_to_string(YH_HMAC_KEY, &string); assert(yrc == YHR_SUCCESS && strcmp(string, "hmac-key") == 0); yrc = yh_type_to_string(YH_TEMPLATE, &string); assert(yrc == YHR_SUCCESS && strcmp(string, "template") == 0); yrc = yh_type_to_string(YH_OTP_AEAD_KEY, &string); assert(yrc == YHR_SUCCESS && strcmp(string, "otp-aead-key") == 0); } int main(void) { yh_init(); test_domains1(); test_domains2(); test_capabilities1(); test_capabilities2(); test_capabilities3(); test_algorithms(); test_options(); test_types(); return 0; } yubihsm-shell-2.7.1/lib/lib_util.c0000644000175100017510000001162215133003406016426 0ustar runnerrunner/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include "yubihsm.h" #include "internal.h" #include "debug_lib.h" #ifdef __WIN32 #include #else #include #endif #define STATUS_STR "status=" #define VERSION_STR "version=" #define PID_STR "pid=" #define ADDRESS_STR "address=" #define PORT_STR "port=" #ifdef _MSVC #define strtok_r strtok_s #endif void dump_hex(FILE *file, const uint8_t *ptr, uint16_t len) { uint32_t i; for (i = 0; i < len; i++) { if (i && !(i % 8)) { fprintf(file, " "); } fprintf(file, "%02x", ptr[i]); } } void dump_msg(FILE *file, const Msg *msg) { fprintf(file, "SEND >> (03 + %04d) %02x %04x ", ntohs(msg->st.len), msg->st.cmd, ntohs(msg->st.len)); dump_hex(file, msg->st.data, ntohs(msg->st.len)); fprintf(file, "\n"); } void dump_response(FILE *file, const Msg *msg) { fprintf(file, "RECV << (03 + %04d) %02x %04x ", ntohs(msg->st.len), msg->st.cmd, ntohs(msg->st.len)); dump_hex(file, msg->st.data, ntohs(msg->st.len)); fprintf(file, " \n"); } void parse_status_data(char *data, yh_connector *connector) { char *saveptr = NULL; char *str = NULL; while ((str = strtok_r(str ? NULL : data, "\n", &saveptr))) { if (strncmp(str, STATUS_STR, strlen(STATUS_STR)) == 0) { if (strcmp(str + strlen(STATUS_STR), "OK") == 0) { connector->has_device = true; } else { connector->has_device = false; } } else if (strncmp(str, VERSION_STR, strlen(VERSION_STR)) == 0) { unsigned long v_maj = 0; unsigned long v_min = 0; unsigned long v_pat = 0; str = str + strlen(VERSION_STR); if (sscanf(str, "%lu.%lu.%lu", &v_maj, &v_min, &v_pat) <= 3) { DBG_ERR("Unable to parse version string"); continue; } connector->version_major = v_maj; connector->version_minor = v_min; connector->version_patch = v_pat; } else if (strncmp(str, PID_STR, strlen(PID_STR)) == 0) { char *endptr; unsigned long pid; str = str + strlen(PID_STR); errno = 0; pid = strtoul(str, &endptr, 0); if ((errno == ERANGE && pid == ULONG_MAX) || (errno != 0 && pid == 0)) { continue; } if (endptr == str || pid == 0) { continue; } connector->pid = pid; } else if (strncmp(str, ADDRESS_STR, strlen(ADDRESS_STR)) == 0) { strncpy(connector->address, str + strlen(ADDRESS_STR), sizeof(connector->address) - 1); } else if (strncmp(str, PORT_STR, strlen(PORT_STR)) == 0) { char *endptr; unsigned long port; str = str + strlen(PORT_STR); errno = 0; port = strtoul(str, &endptr, 0); if ((errno == ERANGE && port == ULONG_MAX) || (errno != 0 && port == 0)) { continue; } if (endptr == str || port == 0) { continue; } connector->port = port; } } DBG_INFO("response from connector"); DBG_INFO("has device: %s", connector->has_device == true ? "yes" : "no"); DBG_INFO("version: %d.%d.%d", connector->version_major, connector->version_minor, connector->version_patch); DBG_INFO("pid: %u", connector->pid); DBG_INFO("address: %s", connector->address); DBG_INFO("port: %u", connector->port); return; } bool parse_usb_url(const char *url, unsigned long *serial) { if (strncmp(url, YH_USB_URL_SCHEME, strlen(YH_USB_URL_SCHEME)) == 0) { url += strlen(YH_USB_URL_SCHEME); char *copy = strdup(url); char *str = NULL; char *saveptr = NULL; // if we don't find a serial we still want to return serial 0 *serial = 0; while ((str = strtok_r(str ? NULL : copy, "&", &saveptr))) { if (strncmp(str, "serial=", strlen("serial=")) == 0) { char *endptr; str += strlen("serial="); errno = 0; *serial = strtoul(str, &endptr, 10); if ((errno == ERANGE && *serial == ULONG_MAX) || endptr == str || *endptr != '\0' || (errno != 0 && *serial == 0)) { *serial = 0; DBG_ERR("Failed to parse serial argument: '%s'.", str); free(copy); return false; } } else { DBG_INFO("Unknown USB option '%s'.", str); } } DBG_INFO("USB url parsed with serial decimal %lu.", *serial); free(copy); return true; } return false; } yubihsm-shell-2.7.1/lib/Doxyfile0000644000175100017510000031732515133003406016176 0ustar runnerrunner# Doxyfile 1.8.11 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = "libyubihsm" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = doxygen # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new # page for each member. If set to NO, the documentation of a member will be part # of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: # FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: # Fortran. In the later case the parser tries to guess whether the code is fixed # or free formatted code, this is the default for Fortran type files), VHDL. For # instance to make doxygen treat .inc files as Fortran files (default is PHP), # and .f files as C (default is Fortran), use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or # globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # If one adds a struct or class to a group and this option is enabled, then also # any nested class or struct is added to the same group. By default this option # is disabled and one has to add nested compounds explicitly via \ingroup. # The default value is: NO. GROUP_NESTED_COMPOUNDS = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO, only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option # has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO, these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES, upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. HIDE_COMPOUND_REFERENCE= NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = NO # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = YES # The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo # list. This list is created by putting \todo commands in the documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test # list. This list is created by putting \test commands in the documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, doxygen will only warn about wrong or incomplete # parameter documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = YES # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # a warning is encountered. # The default value is: NO. WARN_AS_ERROR = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. INPUT = yubihsm.h # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: http://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, # *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl, # *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js. FILE_PATTERNS = # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see http://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES # If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the # clang parser (see: http://clang.llvm.org/) for more accurate parsing at the # cost of reduced performance. This can be particularly helpful with template # rich C++ code for which doxygen's built-in parser lacks the necessary type # information. # Note: The availability of this option depends on whether or not doxygen was # generated with the -Duse-libclang=ON option for CMake. # The default value is: NO. CLANG_ASSISTED_PARSING = NO # If clang assisted parsing is enabled you can provide the compiler with command # line options that you would normally use when invoking the compiler. Note that # the include paths will already be set by doxygen for the files and directories # specified with INPUT and INCLUDE_PATH. # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. CLANG_OPTIONS = #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to YES can help to show when doxygen was last run and thus if the # documentation is up to date. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = NO # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: http://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated # (YES) or that it should be included in the main .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from http://www.mathjax.org before deployment. # The default value is: http://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /