summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2015-09-19 16:17:20 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2015-09-19 16:17:20 -0500
commit68dc59cb2bfdd5c6be1054f62e89cf11354588de (patch)
tree092fbbb135e4555639e4a903ffbec900770b43c2
parent640e6672c36985234929fc94a1b8288a82427699 (diff)
downloadsmartcardauth-68dc59cb.tar.gz
smartcardauth-68dc59cb.zip
Add autoPIN support
-rw-r--r--src/cardpincheck.c73
1 files changed, 72 insertions, 1 deletions
diff --git a/src/cardpincheck.c b/src/cardpincheck.c
index c79012b..e6c1cc4 100644
--- a/src/cardpincheck.c
+++ b/src/cardpincheck.c
@@ -18,9 +18,11 @@
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
+#include <string.h>
#include <pkcs11-helper-1.0/pkcs11h-certificate.h>
#include <pkcs11-helper-1.0/pkcs11h-openssl.h>
+#include <openssl/x509v3.h>
#define CARD_MAX_LOGIN_RETRY_COUNT 3
@@ -82,7 +84,7 @@ static PKCS11H_BOOL pkcs_pin_hook(IN void * const global_data, IN void * const u
if (cached_pin) {
free(cached_pin);
}
- cached_pin= malloc(sizeof(char) * pin_max);
+ cached_pin = malloc(sizeof(char) * pin_max);
snprintf(cached_pin, pin_max, "%s", line);
// Copy PIN to buffer
@@ -102,6 +104,68 @@ static void pkcs_log_hook(IN void * const global_data, IN unsigned flags, IN con
}
}
+char* tde_autopin(X509* x509_cert) {
+ char* retString = NULL;
+ int i;
+
+ // Use subjAltName field in card certificate to provide the card's PIN,
+ // in order to support optional pin-less operation.
+ // Parse the TDE autologin extension
+ // Structure:
+ // OID 1.3.6.1.4.1.40364.1.2.1
+ // SEQUENCE
+ // ASN1_CONSTRUCTED [index: 0] (field name: pin)
+ // GeneralString
+
+ // Register custom OID type for TDE autopin data
+ ASN1_OBJECT* tde_autopin_data_object = OBJ_txt2obj("1.3.6.1.4.1.40364.1.2.1", 0);
+
+ GENERAL_NAMES* subjectAltNames = (GENERAL_NAMES*)X509_get_ext_d2i(x509_cert, NID_subject_alt_name, NULL, NULL);
+ int altNameCount = sk_GENERAL_NAME_num(subjectAltNames);
+ for (i=0; i < altNameCount; i++) {
+ GENERAL_NAME* generalName = sk_GENERAL_NAME_value(subjectAltNames, i);
+ if (generalName->type == GEN_OTHERNAME) {
+ OTHERNAME* otherName = generalName->d.otherName;
+ if (!OBJ_cmp(otherName->type_id, tde_autopin_data_object)) {
+ ASN1_TYPE* asnValue = otherName->value;
+ if (asnValue) {
+ // Found autopin structure
+ int index;
+ ASN1_TYPE* asnSeqValue = NULL;
+ ASN1_GENERALSTRING* asnGeneralString = NULL;
+ STACK_OF(ASN1_TYPE) *asnSeqValueStack = NULL;
+ long asn1SeqValueObjectLength;
+ int asn1SeqValueObjectTag;
+ int asn1SeqValueObjectClass;
+ int returnCode;
+
+ index = 0; // Search for the PIN field
+ asnSeqValueStack = ASN1_seq_unpack_ASN1_TYPE(ASN1_STRING_data(asnValue->value.sequence), ASN1_STRING_length(asnValue->value.sequence), d2i_ASN1_TYPE, ASN1_TYPE_free);
+ asnSeqValue = sk_ASN1_TYPE_value(asnSeqValueStack, index);
+ if (asnSeqValue) {
+ if (asnSeqValue->value.octet_string->data[0] == ((V_ASN1_CONSTRUCTED | V_ASN1_CONTEXT_SPECIFIC) + index)) {
+ const unsigned char* asn1SeqValueObjectData = asnSeqValue->value.sequence->data;
+ returnCode = ASN1_get_object(&asn1SeqValueObjectData, &asn1SeqValueObjectLength, &asn1SeqValueObjectTag, &asn1SeqValueObjectClass, asnSeqValue->value.sequence->length);
+ if (!(returnCode & 0x80)) {
+ if (returnCode == (V_ASN1_CONSTRUCTED + index)) {
+ if (d2i_ASN1_GENERALSTRING(&asnGeneralString, &asn1SeqValueObjectData, asn1SeqValueObjectLength) != NULL) {
+ retString = strdup(ASN1_STRING_data(asnGeneralString));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Clean up
+ OBJ_cleanup();
+
+ return retString;
+}
+
int main(int argc, char* argv[]) {
CK_RV rv;
pkcs11h_certificate_id_list_t issuers;
@@ -203,6 +267,13 @@ int main(int argc, char* argv[]) {
ret = -1;
}
+ // Check for TDE autopin structure
+ char* autopin = tde_autopin(x509_local);
+ if (autopin) {
+ cached_pin = autopin;
+ use_cached_pin = 1;
+ }
+
// Extract public key from X509 certificate
EVP_PKEY* x509_pubkey = NULL;
x509_pubkey = X509_get_pubkey(x509_local);