/** * Decode a TLV encoded PKCS#15 private key description into a structure * * The caller must use freePrivateKeyDescription() to free the allocated structure * * @param prkd The first byte of the encoded structure * @param prkdlen The length of the encoded structure * @param p15 Pointer to pointer updated with the newly allocated structure * @return 0 if successfull, -1 for structural errors */ int decodePrivateKeyDescription(unsigned char *prkd, size_t prkdlen, struct p15PrivateKeyDescription **p15) { int rc,tag,len; unsigned char *po; rc = asn1Validate(prkd, prkdlen); if (rc != 0) { return -1; } *p15 = calloc(1, sizeof(struct p15PrivateKeyDescription)); if (*p15 == NULL) { return -1; } po = prkd; tag = asn1Tag(&po); len = asn1Length(&po); if ((tag != ASN1_SEQUENCE) && (tag != 0xA0)) { return -1; } (*p15)->keytype = (int)tag; rc = decodePrivateKeyAttributes(po, len, *p15); return rc; }
/** * Decode a TLV encoded PKCS#15 certificate description into a structure * * The caller must use freeCertificateDescription() to free the allocated structure * * @param cd The first byte of the encoded structure * @param cdlen The length of the encoded structure * @param p15 Pointer to pointer updated with the newly allocated structure * @return 0 if successful, -1 for structural errors */ int decodeCertificateDescription(unsigned char *cd, size_t cdlen, struct p15CertificateDescription **p15) { int rc,tag,len; unsigned char *po; rc = asn1Validate(cd, cdlen); if (rc != 0) { return -1; } *p15 = calloc(1, sizeof(struct p15CertificateDescription)); if (*p15 == NULL) { return -1; } po = cd; tag = asn1Tag(&po); len = asn1Length(&po); if ((tag != ASN1_SEQUENCE) && (tag != 0xA0)) { return -1; } (*p15)->certtype = (int)tag; rc = decodeCertificateAttributes(po, len, *p15); return rc; }
int IsEMVCard(int fd,uint64_t *pStatus) { unsigned char cmd_buffer[261]; unsigned char rsp_buffer[258]; size_t rx_frame_size; uint8_t rx_last_bits; char *SELECT_2PAY_SYS = "\x00\xA4\x04\x00\x0E\x32\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31\x00"; int rc; /* Select 2PAY.SYS.DDF01 */ rc = feclr_transceive(fd, 0, SELECT_2PAY_SYS, 20, 0, rsp_buffer, sizeof(rsp_buffer), &rx_frame_size, &rx_last_bits, 0, pStatus); if (rc < 0) { return rc; } if (!verify_icc_response(rsp_buffer, rx_frame_size, 0x9000)) { if (asn1Validate(rsp_buffer, rx_frame_size - 2) == 0) { rc = check_2pay_sys(rsp_buffer, rx_frame_size); printf(" check_2pay_sys rc value = %d\n",rc); if (rc == 1) { /* MASTER Card detected */ printf(" MASTER Card detected\n"); return 1; } else if (rc == 2) { /* VISA Card detected */ printf("VISA Card detected\n"); return 1; } else if (rc == 3) { /* AMEX Card detected */ printf("AMEX Card detected\n"); return 1; } else if (rc == 4) { /* DISCOVER Card detected */ printf("DISCOVER Card detected\n"); return 1; } else if (rc == 5) { /* GIROGO Card detected */ printf("GIROGO Card detected\n"); visualization_girogo(); return 0; } } } return 0; }
/** * Populate the attribute CKA_ISSUER, CKA_SUBJECT and CKA_SERIAL from certificate */ int populateIssuerSubjectSerial(struct p11Object_t *object) { CK_ATTRIBUTE attr = { CKA_VALUE, NULL, 0 }; struct p11Attribute_t *pattr; int tag, length, buflen; unsigned char *value, *cursor, *obj; attr.type = CKA_VALUE; if (findAttribute(object, &attr, &pattr) < 0) { return -1; } cursor = pattr->attrData.pValue; buflen = pattr->attrData.ulValueLen; if (asn1Validate(cursor, buflen)) { return -1; } // Outer SEQUENCE if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { return -1; } cursor = value; buflen = length; // TBS SEQUENCE if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { return -1; } cursor = value; buflen = length; obj = cursor; if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { return -1; } if (tag == 0xA0) { // Skip optional cert type obj = cursor; if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { return -1; } } if (tag != ASN1_INTEGER) { return -1; } attr.type = CKA_SERIAL_NUMBER; attr.pValue = obj; attr.ulValueLen = (CK_ULONG)(cursor - obj); addAttribute(object, &attr); if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { // Skip SignatureAlgorithm return -1; } obj = cursor; if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { // Decode Issuer return -1; } if (tag != ASN1_SEQUENCE) { return -1; } attr.type = CKA_ISSUER; attr.pValue = obj; attr.ulValueLen = (CK_ULONG)(cursor - obj); addAttribute(object, &attr); if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { // Skip validity dates return -1; } obj = cursor; if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { // Decode Subject return -1; } if (tag != ASN1_SEQUENCE) { return -1; } attr.type = CKA_SUBJECT; attr.pValue = obj; attr.ulValueLen = (CK_ULONG)(cursor - obj); addAttribute(object, &attr); return 0; }
int decodeModulusExponentFromSPKI(unsigned char *spki, CK_ATTRIBUTE_PTR modulus, CK_ATTRIBUTE_PTR exponent) { int tag, length, buflen; unsigned char *value, *cursor; cursor = spki; // spk is ASN.1 validated before, not need to check again // subjectPublicKeyInfo tag = asn1Tag(&cursor); if (tag != ASN1_SEQUENCE) { return -1; } buflen = asn1Length(&cursor); // algorithm if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { return -1; } if (tag != ASN1_SEQUENCE) { return -1; } // subjectPublicKey if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { return -1; } if (tag != ASN1_BIT_STRING) { return -1; } if (length < 6) { return -1; } cursor = value + 1; buflen = length - 1; if (asn1Validate(cursor, buflen) != 0) { return -1; } // Outer SEQUENCE if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { return -1; } if (tag != ASN1_SEQUENCE) { return -1; } cursor = value; buflen = length; // Modulus if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { return -1; } if (tag != ASN1_INTEGER) { return -1; } modulus->type = CKA_MODULUS; modulus->pValue = value; modulus->ulValueLen = length; // Exponent if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { return -1; } if (tag != ASN1_INTEGER) { return -1; } exponent->type = CKA_PUBLIC_EXPONENT; exponent->pValue = value; exponent->ulValueLen = length; return 0; }
int getSubjectPublicKeyInfo(struct p11Object_t *object, unsigned char **spki) { CK_ATTRIBUTE attr = { CKA_VALUE, NULL, 0 }; struct p11Attribute_t *pattr; int tag, length, buflen; unsigned char *value, *cursor; attr.type = CKA_VALUE; if (findAttribute(object, &attr, &pattr) < 0) { return -1; } cursor = pattr->attrData.pValue; buflen = pattr->attrData.ulValueLen; if (asn1Validate(cursor, buflen)) { return -1; } // Outer SEQUENCE if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { return -1; } cursor = value; buflen = length; // TBS SEQUENCE if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { return -1; } cursor = value; buflen = length; if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { return -1; } if (tag == 0xA0) { // Skip optional cert type if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { return -1; } } if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { // Skip SignatureAlgorithm return -1; } if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { // Skip Issuer return -1; } if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { // Skip validity dates return -1; } if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { // Skip Subject return -1; } *spki =cursor; if (!asn1Next(&cursor, &buflen, &tag, &length, &value)) { // Skip SubjectPublicKeyInfo return -1; } if (tag != ASN1_SEQUENCE) { return -1; } return 0; }
static int decodeECDSASignature(unsigned char *data, int datalen, unsigned char *out, int outlen) { int fieldsizebytes, i, r, taglen; unsigned char *po, *value; FUNC_CALLED(); r = asn1Validate(data, datalen); if (r != 0) { FUNC_FAILS(-1, "Signature is not a valid TLV structure"); } // Determine field size from length of signature if (datalen <= 58) { // 192 bit curve = 24 * 2 + 10 byte maximum DER signature fieldsizebytes = 24; } else if (datalen <= 66) { // 224 bit curve = 28 * 2 + 10 byte maximum DER signature fieldsizebytes = 28; } else if (datalen <= 74) { // 256 bit curve = 32 * 2 + 10 byte maximum DER signature fieldsizebytes = 32; } else if (datalen <= 90) { // 320 bit curve = 40 * 2 + 10 byte maximum DER signature fieldsizebytes = 40; } else { fieldsizebytes = 64; } #ifdef DEBUG debug("Field size %d, signature buffer size %d\n", fieldsizebytes, outlen); #endif if (outlen < (fieldsizebytes * 2)) { FUNC_FAILS(-1, "output too small for EC signature"); } memset(out, 0, outlen); po = data; if (asn1Tag(&po) != ASN1_SEQUENCE) { FUNC_FAILS(-1, "Signature not encapsulated in SEQUENCE"); } r = asn1Length(&po); if ((r < 8) || (r > 137)) { FUNC_FAILS(-1, "Invalid signature size"); } for (i = 0; i < 2; i++) { if (asn1Tag(&po) != ASN1_INTEGER) { FUNC_FAILS(-1, "Coordinate not encapsulated in INTEGER"); } taglen = asn1Length(&po); value = po; po += taglen; if (taglen > fieldsizebytes) { /* drop leading 00 if present */ if (*value != 0x00) { FUNC_FAILS(-1, "Invalid value in coordinate"); } value++; taglen--; } memcpy(out + fieldsizebytes * i + fieldsizebytes - taglen , value, taglen); } FUNC_RETURNS(fieldsizebytes << 1); }
int starcosDeterminePinUseCounter(struct p11Token_t *token, unsigned char recref, int *useCounter, int *lifeCycle) { int rc,ucpathlen; unsigned short SW1SW2; unsigned char rec[256], *p,*fid,*ucpath; FUNC_CALLED(); if (token->info.firmwareVersion.minor >= 5) { fid = (unsigned char *)"\x00\x13"; // EF.KEYD ucpath = (unsigned char *)"\x30\x7B\xA4\x9F\x22"; ucpathlen = 4; // 4 Tags (not bytes) } else { fid = (unsigned char *)"\x00\x15"; // EF.PWDD ucpath = (unsigned char *)"\x30\x7B\x9F\x22"; ucpathlen = 3; // 3 Tags (not bytes) } // Select EF rc = transmitAPDU(token->slot, 0x00, 0xA4, 0x02, 0x0C, 2, fid, 0, NULL, 0, &SW1SW2); if (rc < 0) { FUNC_FAILS(rc, "transmitAPDU failed"); } if (SW1SW2 != 0x9000) { FUNC_FAILS(-1, "File not found"); } // Read record, but leave 3 bytes to add encapsulating 30 81 FF later rc = transmitAPDU(token->slot, 0x00, 0xB2, recref, 0x04, 0, NULL, 0, rec, sizeof(rec) - 3, &SW1SW2); if (rc < 0) { FUNC_FAILS(rc, "transmitAPDU failed"); } if (SW1SW2 != 0x9000) { FUNC_FAILS(-1, "Record not found"); } rc = asn1Encap(0x30, rec, rc); rc = (int)asn1Validate(rec, rc); if (rc > 0) { FUNC_FAILS(rc, "ASN.1 structure invalid"); } *useCounter = 0; p = asn1Find(rec, ucpath, ucpathlen); if (p) { asn1Tag(&p); asn1Length(&p); *useCounter = (*p == 0xFF ? 0 : *p); } p = asn1Find(rec, (unsigned char *)"\x30\x8A", 2); if (p) { asn1Tag(&p); asn1Length(&p); *lifeCycle = *p; } FUNC_RETURNS(CKR_OK); }