defensive-coding-guide/src/HSM-OpenSSL.c
Nikos Mavrogiannopoulos 9a936ea6b7 Added a section on usage of Hardware Security Modules (HSM).
The NSS parts were contributed by Robert Relyea.
2017-03-28 14:17:00 +02:00

129 lines
2.8 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <err.h>
#include <arpa/inet.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/engine.h>
#include <openssl/conf.h>
static void display_openssl_errors(int l)
{
const char *file;
char buf[120];
int e, line;
if (ERR_peek_error() == 0)
return;
fprintf(stderr, "At %s:%d:\n", __FILE__, l);
while ((e = ERR_get_error_line(&file, &line))) {
ERR_error_string(e, buf);
fprintf(stderr, "- SSL %s: %s:%d\n", buf, file, line);
}
}
/* This program accepts on the command line:
* 1. A PKCS#11 URL specifying a private key
* 2. A PIN
* 3. A PKCS#11 shared module (optional)
*
* And signs test data with the provided key.
*
* Example: ./a.out "pkcs11:object=myobject" 1234 /usr/lib64/pkcs11/opensc-pkcs11.so
*/
int main(int argc, char **argv)
{
char *private_key_name;
unsigned char buf[4096];
const EVP_MD *digest_algo;
EVP_PKEY *private_key;
char *key_pass = NULL;
unsigned n;
ENGINE *e;
EVP_MD_CTX ctx;
const char *module_path = NULL;
if (argc < 2) {
fprintf(stderr, "usage: %s [private key URL] [PIN] [module]\n", argv[0]);
fprintf(stderr, "\n");
exit(1);
}
private_key_name = argv[1];
key_pass = argv[2];
if (argc >= 3)
module_path = argv[3];
//+ Features HSM-OpenSSL
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
ERR_clear_error();
ENGINE_load_builtin_engines();
e = ENGINE_by_id("pkcs11");
if (!e) {
display_openssl_errors(__LINE__);
exit(1);
}
if (module_path) {
fprintf(stderr, "loading: %s\n", module_path);
if (!ENGINE_ctrl_cmd_string(e, "MODULE_PATH", module_path, 0)) {
display_openssl_errors(__LINE__);
exit(1);
}
}
if (!ENGINE_init(e)) {
display_openssl_errors(__LINE__);
exit(1);
}
if (key_pass && !ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0)) {
display_openssl_errors(__LINE__);
exit(1);
}
private_key = ENGINE_load_private_key(e, private_key_name, NULL, NULL);
if (!private_key) {
fprintf(stderr, "cannot load: %s\n", private_key_name);
display_openssl_errors(__LINE__);
exit(1);
}
display_openssl_errors(__LINE__);
digest_algo = EVP_get_digestbyname("sha256");
EVP_MD_CTX_init(&ctx);
if (EVP_DigestInit(&ctx, digest_algo) <= 0) {
display_openssl_errors(__LINE__);
exit(1);
}
EVP_SignInit(&ctx, digest_algo);
#define TEST_DATA "test data"
if (EVP_SignUpdate(&ctx, TEST_DATA, sizeof(TEST_DATA) - 1) <= 0) {
display_openssl_errors(__LINE__);
exit(1);
}
n = sizeof(buf);
if (EVP_SignFinal(&ctx, buf, &n, private_key) <= 0) {
display_openssl_errors(__LINE__);
exit(1);
}
EVP_PKEY_free(private_key);
ENGINE_finish(e);
//-
return 0;
}