Blame examples/decrypt.c

Packit 6b81fa
/* libp11 example code: auth.c
Packit 6b81fa
 *
Packit 6b81fa
 * This examply simply connects to your smart card
Packit 6b81fa
 * and does a public key authentication.
Packit 6b81fa
 *
Packit 6b81fa
 * Feel free to copy all of the code as needed.
Packit 6b81fa
 *
Packit 6b81fa
 */
Packit 6b81fa
Packit 6b81fa
#include <sys/types.h>
Packit 6b81fa
#include <sys/stat.h>
Packit 6b81fa
#include <fcntl.h>
Packit 6b81fa
#include <unistd.h>
Packit 6b81fa
#if !defined(_WIN32) || defined(__CYGWIN__)
Packit 6b81fa
#include <termios.h>
Packit 6b81fa
#endif
Packit 6b81fa
#include <stdio.h>
Packit 6b81fa
#include <string.h>
Packit 6b81fa
#include <libp11.h>
Packit 6b81fa
Packit 6b81fa
#define RANDOM_SOURCE "/dev/urandom"
Packit 6b81fa
#define RANDOM_SIZE 64
Packit 6b81fa
#define MAX_SIGSIZE 256
Packit 6b81fa
Packit 6b81fa
int main(int argc, char *argv[])
Packit 6b81fa
{
Packit 6b81fa
	PKCS11_CTX *ctx;
Packit 6b81fa
	PKCS11_SLOT *slots, *slot;
Packit 6b81fa
	PKCS11_CERT *certs;
Packit 6b81fa
	
Packit 6b81fa
	PKCS11_KEY *authkey;
Packit 6b81fa
	PKCS11_CERT *authcert;
Packit 6b81fa
	EVP_PKEY *pubkey = NULL;
Packit 6b81fa
Packit 6b81fa
	unsigned char *random = NULL, *encrypted = NULL, *decrypted = NULL;
Packit 6b81fa
Packit 6b81fa
	char password[20];
Packit 6b81fa
	int rc, fd, len;
Packit 6b81fa
	unsigned int nslots, ncerts;
Packit 6b81fa
Packit 6b81fa
	/* get password */
Packit 6b81fa
#if !defined(_WIN32) || defined(__CYGWIN__)
Packit 6b81fa
	struct termios old, new;
Packit 6b81fa
#endif
Packit 6b81fa
	if (argc != 2) {
Packit 6b81fa
		fprintf(stderr, "usage: auth /usr/lib/opensc-pkcs11.so\n");
Packit 6b81fa
		return 1;
Packit 6b81fa
	}
Packit 6b81fa
Packit 6b81fa
	ctx = PKCS11_CTX_new();
Packit 6b81fa
Packit 6b81fa
	/* load pkcs #11 module */
Packit 6b81fa
	rc = PKCS11_CTX_load(ctx, argv[1]);
Packit 6b81fa
	if (rc) {
Packit 6b81fa
		fprintf(stderr, "loading pkcs11 engine failed: %s\n",
Packit 6b81fa
			ERR_reason_error_string(ERR_get_error()));
Packit 6b81fa
		rc = 1;
Packit 6b81fa
		goto nolib;
Packit 6b81fa
	}
Packit 6b81fa
Packit 6b81fa
	/* get information on all slots */
Packit 6b81fa
	rc = PKCS11_enumerate_slots(ctx, &slots, &nslots);
Packit 6b81fa
	if (rc < 0) {
Packit 6b81fa
		fprintf(stderr, "no slots available\n");
Packit 6b81fa
		rc = 2;
Packit 6b81fa
		goto noslots;
Packit 6b81fa
	}
Packit 6b81fa
Packit 6b81fa
	/* get first slot with a token */
Packit 6b81fa
	slot = PKCS11_find_token(ctx, slots, nslots);
Packit 6b81fa
	if (slot == NULL || slot->token == NULL) {
Packit 6b81fa
		fprintf(stderr, "no token available\n");
Packit 6b81fa
		rc = 3;
Packit 6b81fa
		goto notoken;
Packit 6b81fa
	}
Packit 6b81fa
	printf("Slot manufacturer......: %s\n", slot->manufacturer);
Packit 6b81fa
	printf("Slot description.......: %s\n", slot->description);
Packit 6b81fa
	printf("Slot token label.......: %s\n", slot->token->label);
Packit 6b81fa
	printf("Slot token manufacturer: %s\n", slot->token->manufacturer);
Packit 6b81fa
	printf("Slot token model.......: %s\n", slot->token->model);
Packit 6b81fa
	printf("Slot token serialnr....: %s\n", slot->token->serialnr);
Packit 6b81fa
Packit 6b81fa
	/* get all certs */
Packit 6b81fa
	rc = PKCS11_enumerate_certs(slot->token, &certs, &ncerts);
Packit 6b81fa
	if (rc) {
Packit 6b81fa
		fprintf(stderr, "PKCS11_enumerate_certs failed\n");
Packit 6b81fa
		rc = 4;
Packit 6b81fa
		goto failed;
Packit 6b81fa
	}
Packit 6b81fa
	if (ncerts <= 0) {
Packit 6b81fa
		fprintf(stderr, "no certificates found\n");
Packit 6b81fa
		rc = 5;
Packit 6b81fa
		goto failed;
Packit 6b81fa
	}
Packit 6b81fa
Packit 6b81fa
	/* use the first cert */
Packit 6b81fa
	authcert=&certs[0];
Packit 6b81fa
Packit 6b81fa
	/* get random bytes */
Packit 6b81fa
	random = OPENSSL_malloc(RANDOM_SIZE);
Packit 6b81fa
	if (random == NULL) {
Packit 6b81fa
		rc = 6;
Packit 6b81fa
		goto failed;
Packit 6b81fa
	}
Packit 6b81fa
Packit 6b81fa
	fd = open(RANDOM_SOURCE, O_RDONLY);
Packit 6b81fa
	if (fd < 0) {
Packit 6b81fa
		fprintf(stderr, "fatal: cannot open RANDOM_SOURCE: %s\n",
Packit 6b81fa
				strerror(errno));
Packit 6b81fa
		rc = 7;
Packit 6b81fa
		goto failed;
Packit 6b81fa
	}
Packit 6b81fa
Packit 6b81fa
	rc = read(fd, random, RANDOM_SIZE);
Packit 6b81fa
	if (rc < 0) {
Packit 6b81fa
		fprintf(stderr, "fatal: read from random source failed: %s\n",
Packit 6b81fa
			strerror(errno));
Packit 6b81fa
		close(fd);
Packit 6b81fa
		rc = 8;
Packit 6b81fa
		goto failed;
Packit 6b81fa
	}
Packit 6b81fa
Packit 6b81fa
	if (rc < RANDOM_SIZE) {
Packit 6b81fa
		fprintf(stderr, "fatal: read returned less than %d<%d bytes\n",
Packit 6b81fa
			rc, RANDOM_SIZE);
Packit 6b81fa
		close(fd);
Packit 6b81fa
		rc = 9;
Packit 6b81fa
		goto failed;
Packit 6b81fa
	}
Packit 6b81fa
Packit 6b81fa
	close(fd);
Packit 6b81fa
Packit 6b81fa
	/* get RSA key */
Packit 6b81fa
	pubkey = X509_get_pubkey(authcert->x509);
Packit 6b81fa
	if (pubkey == NULL) {
Packit 6b81fa
		fprintf(stderr, "could not extract public key\n");
Packit 6b81fa
		rc = 10;
Packit 6b81fa
		goto failed;
Packit 6b81fa
	}
Packit 6b81fa
Packit 6b81fa
	/* allocate destination buffer */
Packit 6b81fa
#if OPENSSL_VERSION_NUMBER >= 0x10100003L && !defined(LIBRESSL_VERSION_NUMBER)
Packit 6b81fa
	encrypted = OPENSSL_malloc(RSA_size(EVP_PKEY_get0_RSA(pubkey)));
Packit 6b81fa
#else
Packit 6b81fa
	encrypted = OPENSSL_malloc(RSA_size(pubkey->pkey.rsa));
Packit 6b81fa
#endif
Packit 6b81fa
	if (encrypted == NULL) {
Packit 6b81fa
		fprintf(stderr,"out of memory for encrypted data");
Packit 6b81fa
		rc = 11;
Packit 6b81fa
		goto failed;
Packit 6b81fa
	}
Packit 6b81fa
Packit 6b81fa
	/* use public key for encryption */
Packit 6b81fa
	len = RSA_public_encrypt(RANDOM_SIZE, random, encrypted,
Packit 6b81fa
#if OPENSSL_VERSION_NUMBER >= 0x10100003L && !defined(LIBRESSL_VERSION_NUMBER)
Packit 6b81fa
			EVP_PKEY_get0_RSA(pubkey),
Packit 6b81fa
#else
Packit 6b81fa
			pubkey->pkey.rsa,
Packit 6b81fa
#endif
Packit 6b81fa
			RSA_PKCS1_PADDING);
Packit 6b81fa
	if (len < 0) {
Packit 6b81fa
		fprintf(stderr, "fatal: RSA_public_encrypt failed\n");
Packit 6b81fa
		rc = 12;
Packit 6b81fa
		goto failed;
Packit 6b81fa
	}
Packit 6b81fa
Packit 6b81fa
	/* now decrypt */
Packit 6b81fa
	if (!slot->token->loginRequired)
Packit 6b81fa
		goto loggedin;
Packit 6b81fa
Packit 6b81fa
#if !defined(_WIN32) || defined(__CYGWIN__)
Packit 6b81fa
	/* Turn echoing off and fail if we can't. */
Packit 6b81fa
	if (tcgetattr(0, &old) != 0) {
Packit 6b81fa
		rc = 13;
Packit 6b81fa
		goto failed;
Packit 6b81fa
	}
Packit 6b81fa
Packit 6b81fa
	new = old;
Packit 6b81fa
	new.c_lflag &= ~ECHO;
Packit 6b81fa
	if (tcsetattr(0, TCSAFLUSH, &new) != 0) {
Packit 6b81fa
		rc = 14;
Packit 6b81fa
		goto failed;
Packit 6b81fa
	}
Packit 6b81fa
#endif
Packit 6b81fa
	/* Read the password. */
Packit 6b81fa
	printf("Password for token %.32s: ", slot->token->label);
Packit 6b81fa
	if (fgets(password, sizeof(password), stdin) == NULL) {
Packit 6b81fa
		rc = 15;
Packit 6b81fa
		goto failed;
Packit 6b81fa
	}
Packit 6b81fa
Packit 6b81fa
#if !defined(_WIN32) || defined(__CYGWIN__)
Packit 6b81fa
	/* Restore terminal. */
Packit 6b81fa
	(void)tcsetattr(0, TCSAFLUSH, &old;;
Packit 6b81fa
#endif
Packit 6b81fa
	/* strip tailing \n from password */
Packit 6b81fa
	rc = strlen(password);
Packit 6b81fa
	if (rc <= 0) {
Packit 6b81fa
		rc = 16;
Packit 6b81fa
		goto failed;
Packit 6b81fa
	}
Packit 6b81fa
	password[rc-1]=0;
Packit 6b81fa
Packit 6b81fa
	/* perform pkcs #11 login */
Packit 6b81fa
	rc = PKCS11_login(slot, 0, password);
Packit 6b81fa
	memset(password, 0, strlen(password));
Packit 6b81fa
	if (rc != 0) {
Packit 6b81fa
		fprintf(stderr, "PKCS11_login failed\n");
Packit 6b81fa
		rc = 17;
Packit 6b81fa
		goto failed;
Packit 6b81fa
	}
Packit 6b81fa
Packit 6b81fa
loggedin:
Packit 6b81fa
	authkey = PKCS11_find_key(authcert);
Packit 6b81fa
	if (authkey == NULL) {
Packit 6b81fa
		fprintf(stderr, "no key matching certificate available\n");
Packit 6b81fa
		rc = 18;
Packit 6b81fa
		goto failed;
Packit 6b81fa
	}
Packit 6b81fa
Packit 6b81fa
	/* allocate space for decrypted data */
Packit 6b81fa
#if OPENSSL_VERSION_NUMBER >= 0x10100003L && !defined(LIBRESSL_VERSION_NUMBER)
Packit 6b81fa
	decrypted = OPENSSL_malloc(RSA_size(EVP_PKEY_get0_RSA(pubkey)));
Packit 6b81fa
#else
Packit 6b81fa
	decrypted = OPENSSL_malloc(RSA_size(pubkey->pkey.rsa));
Packit 6b81fa
#endif
Packit 6b81fa
	if (decrypted == NULL) {
Packit 6b81fa
		rc = 19;
Packit 6b81fa
		goto failed;
Packit 6b81fa
	}
Packit 6b81fa
Packit 6b81fa
	rc = PKCS11_private_decrypt(len, encrypted,
Packit 6b81fa
			decrypted, authkey, RSA_PKCS1_PADDING);
Packit 6b81fa
	if (rc != RANDOM_SIZE) {
Packit 6b81fa
		fprintf(stderr, "fatal: PKCS11_private_decrypt failed\n");
Packit 6b81fa
		rc = 20;
Packit 6b81fa
		goto failed;
Packit 6b81fa
	}
Packit 6b81fa
Packit 6b81fa
	/* check if original matches decypted */
Packit 6b81fa
	if (memcmp(random, decrypted, RANDOM_SIZE) != 0) {
Packit 6b81fa
		fprintf(stderr, "fatal: decrypted data does not match original\n");
Packit 6b81fa
		rc = 21;
Packit 6b81fa
		goto failed;
Packit 6b81fa
	}
Packit 6b81fa
Packit 6b81fa
	rc = 0;
Packit 6b81fa
Packit 6b81fa
failed:
Packit 6b81fa
	if (rc)
Packit 6b81fa
		ERR_print_errors_fp(stderr);
Packit 6b81fa
	if (random != NULL)
Packit 6b81fa
		OPENSSL_free(random);
Packit 6b81fa
	if (pubkey != NULL)
Packit 6b81fa
		EVP_PKEY_free(pubkey);
Packit 6b81fa
	if (encrypted != NULL)
Packit 6b81fa
		OPENSSL_free(encrypted);
Packit 6b81fa
	if (decrypted != NULL)
Packit 6b81fa
		OPENSSL_free(decrypted);
Packit 6b81fa
Packit 6b81fa
notoken:
Packit 6b81fa
	PKCS11_release_all_slots(ctx, slots, nslots);
Packit 6b81fa
Packit 6b81fa
noslots:
Packit 6b81fa
	PKCS11_CTX_unload(ctx);
Packit 6b81fa
Packit 6b81fa
nolib:
Packit 6b81fa
	PKCS11_CTX_free(ctx);
Packit 6b81fa
Packit 6b81fa
	if (rc)
Packit 6b81fa
		printf("decryption failed.\n");
Packit 6b81fa
	else
Packit 6b81fa
		printf("decryption successfull.\n");
Packit 6b81fa
	return rc;
Packit 6b81fa
}
Packit 6b81fa
Packit 6b81fa
/* vim: set noexpandtab: */