[pkg-opensc-commit] [libp11] 216/239: Added new example pgm "rawrsasign.c".

Eric Dorland eric at moszumanska.debian.org
Sat Oct 17 06:21:35 UTC 2015


This is an automated email from the git hooks/post-receive script.

eric pushed a commit to branch master
in repository libp11.

commit b9d52f03fbaa4d96999b7c493c2b77100ce60498
Author: Stephane Adenot <stephane.adenot at c-s.fr>
Date:   Mon Aug 31 11:20:00 2015 +0200

    Added new example pgm "rawrsasign.c".
    
    To test and demonstrate PKCS11_private_encrypt() usage with
    RSA_NO_PADDING.
---
 examples/rawrsasign.c    | 301 +++++++++++++++++++++++++++++++++++++++++++++++
 tests/Makefile.am        |   3 +-
 tests/testpkcs11.softhsm |   5 +
 3 files changed, 308 insertions(+), 1 deletion(-)

diff --git a/examples/rawrsasign.c b/examples/rawrsasign.c
new file mode 100644
index 0000000..1e56808
--- /dev/null
+++ b/examples/rawrsasign.c
@@ -0,0 +1,301 @@
+/* libp11 example code: rawrsasign.c
+ *
+ * This example simply connects to your smart card
+ * and demonstrate how to do a raw RSA signing operation with it.
+ *
+ * WARNING: Raw RSA signing *is insecure* and should not be
+ * done without proper padding done elsewhere.
+ * So far, PKCS11_private_encrypt() can only manage PKCS1 padding
+ * and using it with no padding is usefull when padding is
+ * to be done by the software.
+ * This allows to use other padding schemes (like RSA-PSS)
+ * with smart cards, without requiring padding to be done by
+ * the smart card itself.
+ *
+ * Feel free to copy all of the code as needed.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <libp11.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+
+#define RANDOM_SOURCE "/dev/urandom"
+#define RANDOM_SIZE 100
+#define MAX_SIGSIZE 256 /* Should be adapted to the used RSA key size */
+
+#define END(x) do { ret = (x); goto end; } while (0)
+
+int main(int argc, char *argv[])
+{
+    PKCS11_CTX *ctx = NULL;
+    PKCS11_SLOT *slots = NULL, *slot = NULL;
+    PKCS11_CERT *certs = NULL;
+
+    PKCS11_KEY *authkey = NULL;
+    PKCS11_CERT *authcert = NULL;
+    EVP_PKEY *pubkey = NULL;
+    EVP_MD_CTX mctx;
+    EVP_PKEY_CTX *pkeyctx = NULL;
+
+    unsigned char *random = NULL, *signature = NULL;
+
+    char password[20];
+    int rc = 0, fd;
+    unsigned int nslots, ncerts, siglen;
+
+    static unsigned char hash[EVP_MAX_MD_SIZE];
+    static unsigned char enc[MAX_SIGSIZE];
+    static unsigned char pad[MAX_SIGSIZE];
+    unsigned int plen = MAX_SIGSIZE;
+    unsigned int elen = 0;
+    unsigned int hlen = 0;
+    unsigned char* p;
+
+    X509_SIG sig;
+    ASN1_TYPE parameter;
+    X509_ALGOR algorithm;
+    ASN1_OCTET_STRING digest;
+
+    int ret;
+
+    if (argc < 2) {
+        fprintf(stderr, "usage: auth /usr/lib/opensc-pkcs11.so [PIN]\n");
+        END(1);
+    }
+
+    ctx = PKCS11_CTX_new();
+
+    /* load pkcs #11 module */
+    rc = PKCS11_CTX_load(ctx, argv[1]);
+    if (rc) {
+        fprintf(stderr, "loading pkcs11 engine failed: %s\n",
+                ERR_reason_error_string(ERR_get_error()));
+        END(1);
+    }
+
+    /* get information on all slots */
+    rc = PKCS11_enumerate_slots(ctx, &slots, &nslots);
+    if (rc < 0) {
+        fprintf(stderr, "no slots available\n");
+        END(1);
+    }
+
+    /* get first slot with a token */
+    slot = PKCS11_find_token(ctx, slots, nslots);
+    if (!slot || !slot->token) {
+        fprintf(stderr, "no token available\n");
+        END(1);
+    }
+    printf("Slot manufacturer......: %s\n", slot->manufacturer);
+    printf("Slot description.......: %s\n", slot->description);
+    printf("Slot token label.......: %s\n", slot->token->label);
+    printf("Slot token manufacturer: %s\n", slot->token->manufacturer);
+    printf("Slot token model.......: %s\n", slot->token->model);
+    printf("Slot token serialnr....: %s\n", slot->token->serialnr);
+
+    if (!slot->token->loginRequired)
+        goto loggedin;
+
+    /* get password */
+    if (argc > 2) {
+        strcpy(password, argv[2]);
+    } else {
+        struct termios old, new;
+
+        /* Turn echoing off and fail if we can't. */
+        if (tcgetattr(0, &old) != 0)
+            END(1);
+
+        new = old;
+        new.c_lflag &= ~ECHO;
+        if (tcsetattr(0, TCSAFLUSH, &new) != 0)
+            END(1);
+
+        /* Read the password. */
+        printf("Password for token %.32s: ", slot->token->label);
+        fgets(password, sizeof(password), stdin);
+
+        /* Restore terminal. */
+        (void)tcsetattr(0, TCSAFLUSH, &old);
+
+        /* strip tailing \n from password */
+        rc = strlen(password);
+        if (rc <= 0)
+            END(1);
+        password[rc-1]=0;
+    }
+
+loggedin:
+    /* perform pkcs #11 login */
+    rc = PKCS11_login(slot, 0, password);
+    memset(password, 0, strlen(password));
+    if (rc != 0) {
+        fprintf(stderr, "PKCS11_login failed\n");
+        END(1);
+    }
+
+    /* get all certs */
+    rc = PKCS11_enumerate_certs(slot->token, &certs, &ncerts);
+    if (rc) {
+        fprintf(stderr, "PKCS11_enumerate_certs failed\n");
+        END(1);
+    }
+    if (ncerts <= 0) {
+        fprintf(stderr, "no certificates found\n");
+        END(1);
+    }
+
+    /* use the first cert */
+    authcert=&certs[0];
+
+    /* get random bytes */
+    random = malloc(RANDOM_SIZE);
+    if (!random)
+        END(1);
+
+    fd = open(RANDOM_SOURCE, O_RDONLY);
+    if (fd < 0) {
+        fprintf(stderr, "fatal: cannot open RANDOM_SOURCE: %s\n",
+                strerror(errno));
+        END(1);
+    }
+
+    rc = read(fd, random, RANDOM_SIZE);
+    if (rc < 0) {
+        fprintf(stderr, "fatal: read from random source failed: %s\n",
+                strerror(errno));
+        close(fd);
+        END(1);
+    }
+
+    if (rc < RANDOM_SIZE) {
+        fprintf(stderr, "fatal: read returned less than %d<%d bytes\n",
+                rc, RANDOM_SIZE);
+        close(fd);
+        END(1);
+    }
+
+    close(fd);
+
+    authkey = PKCS11_find_key(authcert);
+    if (!authkey) {
+        fprintf(stderr, "no key matching certificate available\n");
+        END(1);
+    }
+
+    /* Compute the SHA1 hash of the random bytes */
+    EVP_MD_CTX_init(&mctx);
+    if (EVP_DigestInit(&mctx, EVP_sha1()) != 1) {
+        fprintf(stderr, "fatal: EVP_DigestInit failed\n");
+        END(1);
+    }
+    if (EVP_DigestUpdate(&mctx, random, RANDOM_SIZE) != 1) {
+        fprintf(stderr, "fatal: EVP_DigestUpdate failed\n");
+        END(1);
+    }
+    if (EVP_DigestFinal(&mctx, hash, &hlen) != 1) {
+        fprintf(stderr, "fatal: EVP_DigestFinal failed\n");
+        END(1);
+    }
+
+    /* Compute a PKCS #1 "block type 01" encryption-block */
+    sig.algor = &algorithm;
+    algorithm.algorithm = OBJ_nid2obj(NID_sha1);
+    parameter.type = V_ASN1_NULL;
+    parameter.value.ptr = NULL;
+    algorithm.parameter = ¶meter;
+    sig.digest = &digest;
+    sig.digest->data = hash;
+    sig.digest->length = hlen;
+    p = enc;
+    elen = i2d_X509_SIG(&sig, &p);
+    p = enc;
+
+    /* Compute PKCS #1 v1.5 padding */
+    if (RSA_padding_add_PKCS1_type_1(pad, plen, p, elen) != 1) {
+        fprintf(stderr, "fatal: RSA_padding_add_PKCS1_type_1 failed\n");
+        END(1);
+    }
+
+    siglen = MAX_SIGSIZE;
+    signature = malloc(MAX_SIGSIZE);
+    if (!signature)
+        END(1);
+
+    /* Do a raw RSA sign operation with the smart card */
+    rc = PKCS11_private_encrypt(plen, pad, signature, authkey, RSA_NO_PADDING);
+    if (rc  < 0) {
+        fprintf(stderr, "PKCS11_private_encrypt failed\n");
+        END(1);
+    }
+
+    /* Verify the signature */
+    /* As we have done a PKCS#1 complient padding, we can verify the signature
+     * with "standard code", using openssl EVP interface.
+     */
+    pubkey = X509_get_pubkey(authcert->x509);
+    if (pubkey == NULL) {
+        fprintf(stderr, "could not extract public key\n");
+        END(1);
+    }
+
+    EVP_MD_CTX_init(&mctx);
+    if (EVP_DigestVerifyInit(&mctx, &pkeyctx, EVP_sha1(), NULL, pubkey) != 1) {
+        fprintf(stderr, "fatal: EVP_DigestVerifyInit failed\n");
+        END(1);
+    }
+
+    if (EVP_PKEY_CTX_set_rsa_padding(pkeyctx, RSA_PKCS1_PADDING) <= 0) {
+        fprintf(stderr, "fatal: EVP_PKEY_CTX_set_rsa_padding failed\n");
+        END(1);
+    }
+
+    if (EVP_DigestVerifyUpdate(&mctx, (const void*)random, RANDOM_SIZE) <= 0) {
+        fprintf(stderr, "fatal: EVP_DigestVerifyUpdate failed\n");
+        END(1);
+    }
+    if ((rc = EVP_DigestVerifyFinal(&mctx, signature, siglen)) != 1) {
+        fprintf(stderr, "fatal: EVP_DigestVerifyFinal failed : %d\n", rc);
+        END(1);
+    }
+
+    printf("raw signing operation and signature verification successfull.\n");
+    ret = 0;
+
+end:
+    if (ret != 0) {
+        ERR_print_errors_fp(stderr);
+        printf("raw signing operation failed.\n");
+    }
+
+    if (pubkey != NULL)
+        EVP_PKEY_free(pubkey);
+    if (random != NULL)
+        free(random);
+    if (signature != NULL)
+        free(signature);
+
+    if (slots != NULL)
+        PKCS11_release_all_slots(ctx, slots, nslots);
+
+    if ( ctx != NULL ) {
+        PKCS11_CTX_unload(ctx);
+        PKCS11_CTX_free(ctx);
+    }
+
+    CRYPTO_cleanup_all_ex_data();
+    ERR_free_strings();
+    ERR_remove_state(0);
+
+    return ret;
+}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 123dc65..95de12b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -9,8 +9,9 @@ AM_LDFLAGS = -no-install
 LDADD = ../src/libp11.la $(OPENSSL_LIBS)
 
 auth_SOURCES = ../examples/auth.c
+rawrsasign_SOURCES = ../examples/rawrsasign.c
 
-check_PROGRAMS = auth fork-test
+check_PROGRAMS = auth fork-test rawrsasign
 dist_check_SCRIPTS = testpkcs11.softhsm testfork.softhsm
 
 TESTS = $(dist_check_SCRIPTS)
diff --git a/tests/testpkcs11.softhsm b/tests/testpkcs11.softhsm
index 2e44718..04109c6 100755
--- a/tests/testpkcs11.softhsm
+++ b/tests/testpkcs11.softhsm
@@ -28,6 +28,11 @@ if test $? != 0;then
 	exit 1;
 fi
 
+./rawrsasign $ADDITIONAL_PARAM $PIN
+if test $? != 0;then
+	exit 1;
+fi
+
 rm -rf "$outdir"
 
 exit 0

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-opensc/libp11.git



More information about the pkg-opensc-commit mailing list