make style

This commit is contained in:
Grayson Martin 2023-07-08 17:58:11 -05:00
commit 1e54cd661c
No known key found for this signature in database
GPG key ID: 4914C62F2696A273
5 changed files with 430 additions and 430 deletions

View file

@ -422,7 +422,7 @@ static command_t CommandTable[] = {
// {"type5", CmdNFCType5, AlwaysAvailable, "{ NFC Forum Tag Type 5... }"}, // {"type5", CmdNFCType5, AlwaysAvailable, "{ NFC Forum Tag Type 5... }"},
{"mf", CmdNFCMF, AlwaysAvailable, "{ NFC Type MIFARE Classic/Plus Tag... }"}, {"mf", CmdNFCMF, AlwaysAvailable, "{ NFC Type MIFARE Classic/Plus Tag... }"},
{"barcode", CmdNFCBarcode, AlwaysAvailable, "{ NFC Barcode Tag... }"}, {"barcode", CmdNFCBarcode, AlwaysAvailable, "{ NFC Barcode Tag... }"},
{"vas", CmdVAS, AlwaysAvailable, "{ Apple Value Added Service }"}, {"vas", CmdVAS, AlwaysAvailable, "{ Apple Value Added Service }"},
// {"--------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("NFC peer-to-peer") " ------------"}, // {"--------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("NFC peer-to-peer") " ------------"},
// {"isodep", CmdISODEP, AlwaysAvailable, "{ ISO-DEP protocol... }"}, // {"isodep", CmdISODEP, AlwaysAvailable, "{ ISO-DEP protocol... }"},
// {"llcp", CmdNFCLLCP, AlwaysAvailable, "{ Logical Link Control Protocol... }"}, // {"llcp", CmdNFCLLCP, AlwaysAvailable, "{ Logical Link Control Protocol... }"},

View file

@ -47,534 +47,534 @@ uint8_t getVasUrlOnlyP2 = 0x00;
uint8_t getVasFullReqP2 = 0x01; uint8_t getVasFullReqP2 = 0x01;
static int ParseSelectVASResponse(uint8_t *response, size_t resLen, bool verbose) { static int ParseSelectVASResponse(uint8_t *response, size_t resLen, bool verbose) {
struct tlvdb *tlvRoot = tlvdb_parse_multi(response, resLen); struct tlvdb *tlvRoot = tlvdb_parse_multi(response, resLen);
struct tlvdb *versionTlv = tlvdb_find_full(tlvRoot, 0x9F21); struct tlvdb *versionTlv = tlvdb_find_full(tlvRoot, 0x9F21);
if (versionTlv == NULL) { if (versionTlv == NULL) {
tlvdb_free(tlvRoot); tlvdb_free(tlvRoot);
return PM3_ECARDEXCHANGE; return PM3_ECARDEXCHANGE;
} }
const struct tlv *version = tlvdb_get_tlv(versionTlv); const struct tlv *version = tlvdb_get_tlv(versionTlv);
if (version->len != 2) { if (version->len != 2) {
tlvdb_free(tlvRoot); tlvdb_free(tlvRoot);
return PM3_ECARDEXCHANGE; return PM3_ECARDEXCHANGE;
} }
if (verbose) { if (verbose) {
PrintAndLogEx(INFO, "Mobile VAS application version: %d.%d", version->value[0], version->value[1]); PrintAndLogEx(INFO, "Mobile VAS application version: %d.%d", version->value[0], version->value[1]);
} }
if (version->value[0] != 0x01 || version->value[1] != 0x00) { if (version->value[0] != 0x01 || version->value[1] != 0x00) {
tlvdb_free(tlvRoot); tlvdb_free(tlvRoot);
return PM3_ECARDEXCHANGE; return PM3_ECARDEXCHANGE;
} }
struct tlvdb *capabilitiesTlv = tlvdb_find_full(tlvRoot, 0x9F23); struct tlvdb *capabilitiesTlv = tlvdb_find_full(tlvRoot, 0x9F23);
if (capabilitiesTlv == NULL) { if (capabilitiesTlv == NULL) {
tlvdb_free(tlvRoot); tlvdb_free(tlvRoot);
return PM3_ECARDEXCHANGE; return PM3_ECARDEXCHANGE;
} }
const struct tlv *capabilities = tlvdb_get_tlv(capabilitiesTlv); const struct tlv *capabilities = tlvdb_get_tlv(capabilitiesTlv);
if (capabilities->len != 4 if (capabilities->len != 4
|| capabilities->value[0] != 0x00 || capabilities->value[0] != 0x00
|| capabilities->value[1] != 0x00 || capabilities->value[1] != 0x00
|| capabilities->value[2] != 0x00 || capabilities->value[2] != 0x00
|| (capabilities->value[3] & 8) == 0) { || (capabilities->value[3] & 8) == 0) {
tlvdb_free(tlvRoot); tlvdb_free(tlvRoot);
return PM3_ECARDEXCHANGE; return PM3_ECARDEXCHANGE;
} }
tlvdb_free(tlvRoot); tlvdb_free(tlvRoot);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int CreateGetVASDataCommand(uint8_t *pidHash, const char *url, size_t urlLen, uint8_t *out, int *outLen) { static int CreateGetVASDataCommand(uint8_t *pidHash, const char *url, size_t urlLen, uint8_t *out, int *outLen) {
if (pidHash == NULL && url == NULL) { if (pidHash == NULL && url == NULL) {
PrintAndLogEx(FAILED, "Must provide a Pass Type ID or a URL"); PrintAndLogEx(FAILED, "Must provide a Pass Type ID or a URL");
return PM3_EINVARG; return PM3_EINVARG;
} }
if (url != NULL && urlLen > 256) { if (url != NULL && urlLen > 256) {
PrintAndLogEx(FAILED, "URL must be less than 256 characters"); PrintAndLogEx(FAILED, "URL must be less than 256 characters");
return PM3_EINVARG; return PM3_EINVARG;
} }
uint8_t p2 = pidHash == NULL ? getVasUrlOnlyP2 : getVasFullReqP2; uint8_t p2 = pidHash == NULL ? getVasUrlOnlyP2 : getVasFullReqP2;
size_t reqTlvLen = 19 + (pidHash != NULL ? 35 : 0) + (url != NULL ? 3 + urlLen : 0); size_t reqTlvLen = 19 + (pidHash != NULL ? 35 : 0) + (url != NULL ? 3 + urlLen : 0);
uint8_t *reqTlv = calloc(reqTlvLen, sizeof(uint8_t)); uint8_t *reqTlv = calloc(reqTlvLen, sizeof(uint8_t));
uint8_t version[] = {0x9F, 0x22, 0x02, 0x01, 0x00}; uint8_t version[] = {0x9F, 0x22, 0x02, 0x01, 0x00};
memcpy(reqTlv, version, sizeof(version)); memcpy(reqTlv, version, sizeof(version));
uint8_t unknown[] = {0x9F, 0x28, 0x04, 0x00, 0x00, 0x00, 0x00}; uint8_t unknown[] = {0x9F, 0x28, 0x04, 0x00, 0x00, 0x00, 0x00};
memcpy(reqTlv + sizeof(version), unknown, sizeof(unknown)); memcpy(reqTlv + sizeof(version), unknown, sizeof(unknown));
uint8_t terminalCapabilities[] = {0x9F, 0x26, 0x04, 0x00, 0x00, 0x00, 0x02}; uint8_t terminalCapabilities[] = {0x9F, 0x26, 0x04, 0x00, 0x00, 0x00, 0x02};
memcpy(reqTlv + sizeof(version) + sizeof(unknown), terminalCapabilities, sizeof(terminalCapabilities)); memcpy(reqTlv + sizeof(version) + sizeof(unknown), terminalCapabilities, sizeof(terminalCapabilities));
if (pidHash != NULL) { if (pidHash != NULL) {
size_t offset = sizeof(version) + sizeof(unknown) + sizeof(terminalCapabilities); size_t offset = sizeof(version) + sizeof(unknown) + sizeof(terminalCapabilities);
reqTlv[offset] = 0x9F; reqTlv[offset] = 0x9F;
reqTlv[offset + 1] = 0x25; reqTlv[offset + 1] = 0x25;
reqTlv[offset + 2] = 32; reqTlv[offset + 2] = 32;
memcpy(reqTlv + offset + 3, pidHash, 32); memcpy(reqTlv + offset + 3, pidHash, 32);
} }
if (url != NULL) { if (url != NULL) {
size_t offset = sizeof(version) + sizeof(unknown) + sizeof(terminalCapabilities) + (pidHash != NULL ? 35 : 0); size_t offset = sizeof(version) + sizeof(unknown) + sizeof(terminalCapabilities) + (pidHash != NULL ? 35 : 0);
reqTlv[offset] = 0x9F; reqTlv[offset] = 0x9F;
reqTlv[offset + 1] = 0x29; reqTlv[offset + 1] = 0x29;
reqTlv[offset + 2] = urlLen; reqTlv[offset + 2] = urlLen;
memcpy(reqTlv + offset + 3, url, urlLen); memcpy(reqTlv + offset + 3, url, urlLen);
} }
out[0] = 0x80; out[0] = 0x80;
out[1] = 0xCA; out[1] = 0xCA;
out[2] = 0x01; out[2] = 0x01;
out[3] = p2; out[3] = p2;
out[4] = reqTlvLen; out[4] = reqTlvLen;
memcpy(out + 5, reqTlv, reqTlvLen); memcpy(out + 5, reqTlv, reqTlvLen);
out[5 + reqTlvLen] = 0x00; out[5 + reqTlvLen] = 0x00;
*outLen = 6 + reqTlvLen; *outLen = 6 + reqTlvLen;
free(reqTlv); free(reqTlv);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int ParseGetVASDataResponse(uint8_t *res, size_t resLen, uint8_t *cryptogram, size_t *cryptogramLen) { static int ParseGetVASDataResponse(uint8_t *res, size_t resLen, uint8_t *cryptogram, size_t *cryptogramLen) {
struct tlvdb *tlvRoot = tlvdb_parse_multi(res, resLen); struct tlvdb *tlvRoot = tlvdb_parse_multi(res, resLen);
struct tlvdb *cryptogramTlvdb = tlvdb_find_full(tlvRoot, 0x9F27); struct tlvdb *cryptogramTlvdb = tlvdb_find_full(tlvRoot, 0x9F27);
if (cryptogramTlvdb == NULL) { if (cryptogramTlvdb == NULL) {
tlvdb_free(tlvRoot); tlvdb_free(tlvRoot);
return PM3_ECARDEXCHANGE; return PM3_ECARDEXCHANGE;
} }
const struct tlv *cryptogramTlv = tlvdb_get_tlv(cryptogramTlvdb); const struct tlv *cryptogramTlv = tlvdb_get_tlv(cryptogramTlvdb);
memcpy(cryptogram, cryptogramTlv->value, cryptogramTlv->len); memcpy(cryptogram, cryptogramTlv->value, cryptogramTlv->len);
*cryptogramLen = cryptogramTlv->len; *cryptogramLen = cryptogramTlv->len;
tlvdb_free(tlvRoot); tlvdb_free(tlvRoot);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int LoadReaderPrivateKey(uint8_t *buf, size_t bufLen, mbedtls_ecp_keypair *privKey) { static int LoadReaderPrivateKey(uint8_t *buf, size_t bufLen, mbedtls_ecp_keypair *privKey) {
struct tlvdb *derRoot = tlvdb_parse_multi(buf, bufLen); struct tlvdb *derRoot = tlvdb_parse_multi(buf, bufLen);
struct tlvdb *privkeyTlvdb = tlvdb_find_full(derRoot, 0x04); struct tlvdb *privkeyTlvdb = tlvdb_find_full(derRoot, 0x04);
if (privkeyTlvdb == NULL) { if (privkeyTlvdb == NULL) {
tlvdb_free(derRoot); tlvdb_free(derRoot);
return PM3_EINVARG; return PM3_EINVARG;
} }
const struct tlv *privkeyTlv = tlvdb_get_tlv(privkeyTlvdb); const struct tlv *privkeyTlv = tlvdb_get_tlv(privkeyTlvdb);
if (mbedtls_ecp_read_key(MBEDTLS_ECP_DP_SECP256R1, privKey, privkeyTlv->value, privkeyTlv->len)) { if (mbedtls_ecp_read_key(MBEDTLS_ECP_DP_SECP256R1, privKey, privkeyTlv->value, privkeyTlv->len)) {
tlvdb_free(derRoot); tlvdb_free(derRoot);
PrintAndLogEx(FAILED, "Unable to parse private key file. Should be DER encoded ASN1"); PrintAndLogEx(FAILED, "Unable to parse private key file. Should be DER encoded ASN1");
return PM3_EINVARG; return PM3_EINVARG;
} }
struct tlvdb *pubkeyCoordsTlvdb = tlvdb_find_full(derRoot, 0x03); struct tlvdb *pubkeyCoordsTlvdb = tlvdb_find_full(derRoot, 0x03);
if (pubkeyCoordsTlvdb == NULL) { if (pubkeyCoordsTlvdb == NULL) {
tlvdb_free(derRoot); tlvdb_free(derRoot);
PrintAndLogEx(FAILED, "Private key file should include public key component"); PrintAndLogEx(FAILED, "Private key file should include public key component");
return PM3_EINVARG; return PM3_EINVARG;
} }
const struct tlv *pubkeyCoordsTlv = tlvdb_get_tlv(pubkeyCoordsTlvdb); const struct tlv *pubkeyCoordsTlv = tlvdb_get_tlv(pubkeyCoordsTlvdb);
if (pubkeyCoordsTlv->len != 66 || pubkeyCoordsTlv->value[0] != 0x00 || pubkeyCoordsTlv->value[1] != 0x04) { if (pubkeyCoordsTlv->len != 66 || pubkeyCoordsTlv->value[0] != 0x00 || pubkeyCoordsTlv->value[1] != 0x04) {
tlvdb_free(derRoot); tlvdb_free(derRoot);
PrintAndLogEx(FAILED, "Invalid public key data"); PrintAndLogEx(FAILED, "Invalid public key data");
return PM3_EINVARG; return PM3_EINVARG;
} }
tlvdb_free(derRoot); tlvdb_free(derRoot);
if (mbedtls_ecp_point_read_binary(&privKey->grp, &privKey->Q, pubkeyCoordsTlv->value + 1, 65)) { if (mbedtls_ecp_point_read_binary(&privKey->grp, &privKey->Q, pubkeyCoordsTlv->value + 1, 65)) {
PrintAndLogEx(FAILED, "Failed to read in public key coordinates"); PrintAndLogEx(FAILED, "Failed to read in public key coordinates");
return PM3_EINVARG; return PM3_EINVARG;
} }
if (mbedtls_ecp_check_pubkey(&privKey->grp, &privKey->Q)) { if (mbedtls_ecp_check_pubkey(&privKey->grp, &privKey->Q)) {
PrintAndLogEx(FAILED, "VAS protocol requires an elliptic key on the P-256 curve"); PrintAndLogEx(FAILED, "VAS protocol requires an elliptic key on the P-256 curve");
return PM3_EINVARG; return PM3_EINVARG;
} }
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int GetPrivateKeyHint(mbedtls_ecp_keypair *privKey, uint8_t *keyHint) { static int GetPrivateKeyHint(mbedtls_ecp_keypair *privKey, uint8_t *keyHint) {
uint8_t xcoord[32] = {0}; uint8_t xcoord[32] = {0};
if (mbedtls_mpi_write_binary(&privKey->Q.X, xcoord, sizeof(xcoord))) { if (mbedtls_mpi_write_binary(&privKey->Q.X, xcoord, sizeof(xcoord))) {
return PM3_EINVARG; return PM3_EINVARG;
} }
uint8_t hash[32] = {0}; uint8_t hash[32] = {0};
sha256hash(xcoord, 32, hash); sha256hash(xcoord, 32, hash);
memcpy(keyHint, hash, 4); memcpy(keyHint, hash, 4);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int LoadMobileEphemeralKey(uint8_t *xcoordBuf, mbedtls_ecp_keypair *pubKey) { static int LoadMobileEphemeralKey(uint8_t *xcoordBuf, mbedtls_ecp_keypair *pubKey) {
uint8_t compressedEcKey[33] = {0}; uint8_t compressedEcKey[33] = {0};
compressedEcKey[0] = 0x02; compressedEcKey[0] = 0x02;
memcpy(compressedEcKey + 1, xcoordBuf, 32); memcpy(compressedEcKey + 1, xcoordBuf, 32);
uint8_t decompressedEcKey[65] = {0}; uint8_t decompressedEcKey[65] = {0};
size_t decompressedEcKeyLen = 0; size_t decompressedEcKeyLen = 0;
if (mbedtls_ecp_decompress(&pubKey->grp, compressedEcKey, sizeof(compressedEcKey), decompressedEcKey, &decompressedEcKeyLen, sizeof(decompressedEcKey))) { if (mbedtls_ecp_decompress(&pubKey->grp, compressedEcKey, sizeof(compressedEcKey), decompressedEcKey, &decompressedEcKeyLen, sizeof(decompressedEcKey))) {
return PM3_EINVARG; return PM3_EINVARG;
} }
if (mbedtls_ecp_point_read_binary(&pubKey->grp, &pubKey->Q, decompressedEcKey, decompressedEcKeyLen)) { if (mbedtls_ecp_point_read_binary(&pubKey->grp, &pubKey->Q, decompressedEcKey, decompressedEcKeyLen)) {
return PM3_EINVARG; return PM3_EINVARG;
} }
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int internalVasDecrypt(uint8_t *cipherText, size_t cipherTextLen, uint8_t *sharedSecret, uint8_t *ansiSharedInfo, size_t ansiSharedInfoLen, uint8_t *gcmAad, size_t gcmAadLen, uint8_t *out, size_t *outLen) { static int internalVasDecrypt(uint8_t *cipherText, size_t cipherTextLen, uint8_t *sharedSecret, uint8_t *ansiSharedInfo, size_t ansiSharedInfoLen, uint8_t *gcmAad, size_t gcmAadLen, uint8_t *out, size_t *outLen) {
uint8_t key[32] = {0}; uint8_t key[32] = {0};
if (ansi_x963_sha256(sharedSecret, 32, ansiSharedInfo, ansiSharedInfoLen, sizeof(key), key)) { if (ansi_x963_sha256(sharedSecret, 32, ansiSharedInfo, ansiSharedInfoLen, sizeof(key), key)) {
PrintAndLogEx(FAILED, "ANSI X9.63 key derivation failed"); PrintAndLogEx(FAILED, "ANSI X9.63 key derivation failed");
return PM3_EINVARG; return PM3_EINVARG;
} }
uint8_t iv[16] = {0}; uint8_t iv[16] = {0};
mbedtls_gcm_context gcmCtx; mbedtls_gcm_context gcmCtx;
mbedtls_gcm_init(&gcmCtx); mbedtls_gcm_init(&gcmCtx);
if (mbedtls_gcm_setkey(&gcmCtx, MBEDTLS_CIPHER_ID_AES, key, sizeof(key) * 8)) { if (mbedtls_gcm_setkey(&gcmCtx, MBEDTLS_CIPHER_ID_AES, key, sizeof(key) * 8)) {
PrintAndLogEx(FAILED, "Unable to use key in GCM context"); PrintAndLogEx(FAILED, "Unable to use key in GCM context");
return PM3_EINVARG; return PM3_EINVARG;
} }
if (mbedtls_gcm_auth_decrypt(&gcmCtx, cipherTextLen - 16, iv, sizeof(iv), gcmAad, gcmAadLen, cipherText + cipherTextLen - 16, 16, cipherText, out)) { if (mbedtls_gcm_auth_decrypt(&gcmCtx, cipherTextLen - 16, iv, sizeof(iv), gcmAad, gcmAadLen, cipherText + cipherTextLen - 16, 16, cipherText, out)) {
PrintAndLogEx(FAILED, "Failed to perform GCM decryption"); PrintAndLogEx(FAILED, "Failed to perform GCM decryption");
return PM3_EINVARG; return PM3_EINVARG;
} }
mbedtls_gcm_free(&gcmCtx); mbedtls_gcm_free(&gcmCtx);
*outLen = cipherTextLen - 16; *outLen = cipherTextLen - 16;
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int DecryptVASCryptogram(uint8_t *pidHash, uint8_t *cryptogram, size_t cryptogramLen, mbedtls_ecp_keypair *privKey, uint8_t *out, size_t *outLen, uint32_t *timestamp) { static int DecryptVASCryptogram(uint8_t *pidHash, uint8_t *cryptogram, size_t cryptogramLen, mbedtls_ecp_keypair *privKey, uint8_t *out, size_t *outLen, uint32_t *timestamp) {
uint8_t keyHint[4] = {0}; uint8_t keyHint[4] = {0};
if (GetPrivateKeyHint(privKey, keyHint) != PM3_SUCCESS) { if (GetPrivateKeyHint(privKey, keyHint) != PM3_SUCCESS) {
PrintAndLogEx(FAILED, "Unable to generate key hint"); PrintAndLogEx(FAILED, "Unable to generate key hint");
return PM3_EINVARG; return PM3_EINVARG;
} }
if (memcmp(keyHint, cryptogram, 4) != 0) { if (memcmp(keyHint, cryptogram, 4) != 0) {
PrintAndLogEx(FAILED, "Private key does not match cryptogram"); PrintAndLogEx(FAILED, "Private key does not match cryptogram");
return PM3_EINVARG; return PM3_EINVARG;
} }
mbedtls_ecp_keypair mobilePubKey;
mbedtls_ecp_keypair_init(&mobilePubKey);
mobilePubKey.grp = privKey->grp;
if (LoadMobileEphemeralKey(cryptogram + 4, &mobilePubKey) != PM3_SUCCESS) {
mbedtls_ecp_keypair_free(&mobilePubKey);
PrintAndLogEx(FAILED, "Unable to parse mobile ephemeral key from cryptogram");
return PM3_EINVARG;
}
mbedtls_mpi sharedSecret; mbedtls_ecp_keypair mobilePubKey;
mbedtls_mpi_init(&sharedSecret); mbedtls_ecp_keypair_init(&mobilePubKey);
mobilePubKey.grp = privKey->grp;
if (mbedtls_ecdh_compute_shared(&privKey->grp, &sharedSecret, &mobilePubKey.Q, &privKey->d, NULL, NULL)) { if (LoadMobileEphemeralKey(cryptogram + 4, &mobilePubKey) != PM3_SUCCESS) {
mbedtls_mpi_free(&sharedSecret); mbedtls_ecp_keypair_free(&mobilePubKey);
mbedtls_ecp_keypair_free(&mobilePubKey); PrintAndLogEx(FAILED, "Unable to parse mobile ephemeral key from cryptogram");
PrintAndLogEx(FAILED, "Failed to generate ECDH shared secret"); return PM3_EINVARG;
return PM3_EINVARG; }
}
mbedtls_ecp_keypair_free(&mobilePubKey);
uint8_t sharedSecretBytes[32] = {0}; mbedtls_mpi sharedSecret;
if (mbedtls_mpi_write_binary(&sharedSecret, sharedSecretBytes, sizeof(sharedSecretBytes))) { mbedtls_mpi_init(&sharedSecret);
mbedtls_mpi_free(&sharedSecret);
PrintAndLogEx(FAILED, "Failed to generate ECDH shared secret");
return PM3_EINVARG;
}
mbedtls_mpi_free(&sharedSecret);
uint8_t string1[27] = "ApplePay encrypted VAS data"; if (mbedtls_ecdh_compute_shared(&privKey->grp, &sharedSecret, &mobilePubKey.Q, &privKey->d, NULL, NULL)) {
uint8_t string2[13] = "id-aes256-GCM"; mbedtls_mpi_free(&sharedSecret);
mbedtls_ecp_keypair_free(&mobilePubKey);
PrintAndLogEx(FAILED, "Failed to generate ECDH shared secret");
return PM3_EINVARG;
}
mbedtls_ecp_keypair_free(&mobilePubKey);
uint8_t method1SharedInfo[73] = {0}; uint8_t sharedSecretBytes[32] = {0};
method1SharedInfo[0] = 13; if (mbedtls_mpi_write_binary(&sharedSecret, sharedSecretBytes, sizeof(sharedSecretBytes))) {
memcpy(method1SharedInfo + 1, string2, sizeof(string2)); mbedtls_mpi_free(&sharedSecret);
memcpy(method1SharedInfo + 1 + sizeof(string2), string1, sizeof(string1)); PrintAndLogEx(FAILED, "Failed to generate ECDH shared secret");
memcpy(method1SharedInfo + 1 + sizeof(string2) + sizeof(string1), pidHash, 32); return PM3_EINVARG;
}
mbedtls_mpi_free(&sharedSecret);
uint8_t decryptedData[68] = {0}; uint8_t string1[27] = "ApplePay encrypted VAS data";
size_t decryptedDataLen = 0; uint8_t string2[13] = "id-aes256-GCM";
if (internalVasDecrypt(cryptogram + 4 + 32, cryptogramLen - 4 - 32, sharedSecretBytes, method1SharedInfo, sizeof(method1SharedInfo), NULL, 0, decryptedData, &decryptedDataLen)) {
if (internalVasDecrypt(cryptogram + 4 + 32, cryptogramLen - 4 - 32, sharedSecretBytes, string1, sizeof(string1), pidHash, 32, decryptedData, &decryptedDataLen)) {
return PM3_EINVARG;
}
}
memcpy(out, decryptedData + 4, decryptedDataLen - 4); uint8_t method1SharedInfo[73] = {0};
*outLen = decryptedDataLen - 4; method1SharedInfo[0] = 13;
memcpy(method1SharedInfo + 1, string2, sizeof(string2));
memcpy(method1SharedInfo + 1 + sizeof(string2), string1, sizeof(string1));
memcpy(method1SharedInfo + 1 + sizeof(string2) + sizeof(string1), pidHash, 32);
*timestamp = 0; uint8_t decryptedData[68] = {0};
for (int i = 0; i < 4; ++i) { size_t decryptedDataLen = 0;
*timestamp = (*timestamp << 8) | decryptedData[i]; if (internalVasDecrypt(cryptogram + 4 + 32, cryptogramLen - 4 - 32, sharedSecretBytes, method1SharedInfo, sizeof(method1SharedInfo), NULL, 0, decryptedData, &decryptedDataLen)) {
} if (internalVasDecrypt(cryptogram + 4 + 32, cryptogramLen - 4 - 32, sharedSecretBytes, string1, sizeof(string1), pidHash, 32, decryptedData, &decryptedDataLen)) {
return PM3_EINVARG;
}
}
return PM3_SUCCESS; memcpy(out, decryptedData + 4, decryptedDataLen - 4);
*outLen = decryptedDataLen - 4;
*timestamp = 0;
for (int i = 0; i < 4; ++i) {
*timestamp = (*timestamp << 8) | decryptedData[i];
}
return PM3_SUCCESS;
} }
static int VASReader(uint8_t *pidHash, const char *url, size_t urlLen, uint8_t *cryptogram, size_t *cryptogramLen, bool verbose) { static int VASReader(uint8_t *pidHash, const char *url, size_t urlLen, uint8_t *cryptogram, size_t *cryptogramLen, bool verbose) {
clearCommandBuffer(); clearCommandBuffer();
uint16_t flags = ISO14A_RAW | ISO14A_CONNECT | ISO14A_NO_SELECT | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT; uint16_t flags = ISO14A_RAW | ISO14A_CONNECT | ISO14A_NO_SELECT | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT;
SendCommandMIX(CMD_HF_ISO14443A_READER, flags, sizeof(ecpData), 0, ecpData, sizeof(ecpData)); SendCommandMIX(CMD_HF_ISO14443A_READER, flags, sizeof(ecpData), 0, ecpData, sizeof(ecpData));
msleep(160); msleep(160);
if (SelectCard14443A_4(false, false, NULL) != PM3_SUCCESS) { if (SelectCard14443A_4(false, false, NULL) != PM3_SUCCESS) {
PrintAndLogEx(FAILED, "No card in field"); PrintAndLogEx(FAILED, "No card in field");
return PM3_ECARDEXCHANGE; return PM3_ECARDEXCHANGE;
} }
uint16_t status = 0; uint16_t status = 0;
size_t resLen = 0; size_t resLen = 0;
uint8_t selectResponse[APDU_RES_LEN] = {0}; uint8_t selectResponse[APDU_RES_LEN] = {0};
Iso7816Select(CC_CONTACTLESS, true, true, aid, sizeof(aid), selectResponse, APDU_RES_LEN, &resLen, &status); Iso7816Select(CC_CONTACTLESS, true, true, aid, sizeof(aid), selectResponse, APDU_RES_LEN, &resLen, &status);
if (status != 0x9000) { if (status != 0x9000) {
PrintAndLogEx(FAILED, "Card doesn't support VAS"); PrintAndLogEx(FAILED, "Card doesn't support VAS");
return PM3_ECARDEXCHANGE; return PM3_ECARDEXCHANGE;
} }
if (ParseSelectVASResponse(selectResponse, resLen, verbose) != PM3_SUCCESS) { if (ParseSelectVASResponse(selectResponse, resLen, verbose) != PM3_SUCCESS) {
PrintAndLogEx(FAILED, "Card doesn't support VAS"); PrintAndLogEx(FAILED, "Card doesn't support VAS");
return PM3_ECARDEXCHANGE; return PM3_ECARDEXCHANGE;
} }
uint8_t getVasApdu[PM3_CMD_DATA_SIZE]; uint8_t getVasApdu[PM3_CMD_DATA_SIZE];
int getVasApduLen = 0; int getVasApduLen = 0;
int s = CreateGetVASDataCommand(pidHash, url, urlLen, getVasApdu, &getVasApduLen); int s = CreateGetVASDataCommand(pidHash, url, urlLen, getVasApdu, &getVasApduLen);
if (s != PM3_SUCCESS) { if (s != PM3_SUCCESS) {
return s; return s;
} }
uint8_t apduRes[APDU_RES_LEN] = {0}; uint8_t apduRes[APDU_RES_LEN] = {0};
int apduResLen = 0; int apduResLen = 0;
s = ExchangeAPDU14a(getVasApdu, getVasApduLen, false, false, apduRes, APDU_RES_LEN, &apduResLen); s = ExchangeAPDU14a(getVasApdu, getVasApduLen, false, false, apduRes, APDU_RES_LEN, &apduResLen);
if (s != PM3_SUCCESS) { if (s != PM3_SUCCESS) {
PrintAndLogEx(FAILED, "Failed to send APDU"); PrintAndLogEx(FAILED, "Failed to send APDU");
return s; return s;
} }
if (apduResLen == 2 && apduRes[0] == 0x62 && apduRes[1] == 0x87) { if (apduResLen == 2 && apduRes[0] == 0x62 && apduRes[1] == 0x87) {
PrintAndLogEx(WARNING, "Device returned error on GET VAS DATA. Either doesn't have pass with matching id, or requires user authentication."); PrintAndLogEx(WARNING, "Device returned error on GET VAS DATA. Either doesn't have pass with matching id, or requires user authentication.");
return PM3_ECARDEXCHANGE; return PM3_ECARDEXCHANGE;
} }
if (apduResLen == 0 || apduRes[0] != 0x70) { if (apduResLen == 0 || apduRes[0] != 0x70) {
PrintAndLogEx(FAILED, "Invalid response from peer"); PrintAndLogEx(FAILED, "Invalid response from peer");
} }
return ParseGetVASDataResponse(apduRes, apduResLen, cryptogram, cryptogramLen); return ParseGetVASDataResponse(apduRes, apduResLen, cryptogram, cryptogramLen);
} }
static int CmdVASReader(const char *Cmd) { static int CmdVASReader(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "nfc vas reader", CLIParserInit(&ctx, "nfc vas reader",
"Read and decrypt VAS message", "Read and decrypt VAS message",
"nfc vas reader -p pass.com.example.ticket -k ./priv.key -> select pass and decrypt with priv.key\nnfc vas reader --url https://example.com -> URL Only mode"); "nfc vas reader -p pass.com.example.ticket -k ./priv.key -> select pass and decrypt with priv.key\nnfc vas reader --url https://example.com -> URL Only mode");
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_str0("p", NULL, "<pid>", "pass type id"), arg_str0("p", NULL, "<pid>", "pass type id"),
arg_str0("k", NULL, "<key>", "path to terminal private key"), arg_str0("k", NULL, "<key>", "path to terminal private key"),
arg_str0(NULL, "url", "<url>", "a URL to provide to the mobile device"), arg_str0(NULL, "url", "<url>", "a URL to provide to the mobile device"),
arg_lit0("@", NULL, "continuous mode"), arg_lit0("@", NULL, "continuous mode"),
arg_lit0("v", "verbose", "log additional information"), arg_lit0("v", "verbose", "log additional information"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
struct arg_str *passTypeIdArg = arg_get_str(ctx, 1); struct arg_str *passTypeIdArg = arg_get_str(ctx, 1);
int passTypeIdLen = arg_get_str_len(ctx, 1); int passTypeIdLen = arg_get_str_len(ctx, 1);
uint8_t pidHash[32] = {0}; uint8_t pidHash[32] = {0};
sha256hash((uint8_t *) passTypeIdArg->sval[0], passTypeIdLen, pidHash); sha256hash((uint8_t *) passTypeIdArg->sval[0], passTypeIdLen, pidHash);
struct arg_str *keyPathArg = arg_get_str(ctx, 2); struct arg_str *keyPathArg = arg_get_str(ctx, 2);
int keyPathLen = arg_get_str_len(ctx, 2); int keyPathLen = arg_get_str_len(ctx, 2);
if (keyPathLen == 0 && passTypeIdLen > 0) { if (keyPathLen == 0 && passTypeIdLen > 0) {
PrintAndLogEx(FAILED, "Must provide path to terminal private key if a pass type id is provided"); PrintAndLogEx(FAILED, "Must provide path to terminal private key if a pass type id is provided");
CLIParserFree(ctx); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
uint8_t *keyData = NULL; uint8_t *keyData = NULL;
size_t keyDataLen = 0; size_t keyDataLen = 0;
if (loadFile_safe(keyPathArg->sval[0], "", (void **)&keyData, &keyDataLen) != PM3_SUCCESS) { if (loadFile_safe(keyPathArg->sval[0], "", (void **)&keyData, &keyDataLen) != PM3_SUCCESS) {
CLIParserFree(ctx); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
mbedtls_ecp_keypair privKey; mbedtls_ecp_keypair privKey;
mbedtls_ecp_keypair_init(&privKey); mbedtls_ecp_keypair_init(&privKey);
if (LoadReaderPrivateKey(keyData, keyDataLen, &privKey) != PM3_SUCCESS) { if (LoadReaderPrivateKey(keyData, keyDataLen, &privKey) != PM3_SUCCESS) {
CLIParserFree(ctx); CLIParserFree(ctx);
mbedtls_ecp_keypair_free(&privKey); mbedtls_ecp_keypair_free(&privKey);
return PM3_EINVARG; return PM3_EINVARG;
} }
free(keyData); free(keyData);
struct arg_str *urlArg = arg_get_str(ctx, 3); struct arg_str *urlArg = arg_get_str(ctx, 3);
int urlLen = arg_get_str_len(ctx, 3); int urlLen = arg_get_str_len(ctx, 3);
const char *url = NULL; const char *url = NULL;
if (urlLen > 0) { if (urlLen > 0) {
url = urlArg->sval[0]; url = urlArg->sval[0];
} }
bool continuous = arg_get_lit(ctx, 4); bool continuous = arg_get_lit(ctx, 4);
bool verbose = arg_get_lit(ctx, 5); bool verbose = arg_get_lit(ctx, 5);
PrintAndLogEx(INFO, "Requesting pass type id: %s", sprint_ascii((uint8_t *) passTypeIdArg->sval[0], passTypeIdLen)); PrintAndLogEx(INFO, "Requesting pass type id: %s", sprint_ascii((uint8_t *) passTypeIdArg->sval[0], passTypeIdLen));
if (continuous) { if (continuous) {
PrintAndLogEx(INFO, "Press " _GREEN_("Enter") " to exit"); PrintAndLogEx(INFO, "Press " _GREEN_("Enter") " to exit");
} }
uint8_t cryptogram[120] = {0}; uint8_t cryptogram[120] = {0};
size_t cryptogramLen = 0; size_t cryptogramLen = 0;
int readerErr = -1; int readerErr = -1;
do { do {
readerErr = VASReader(passTypeIdLen > 0 ? pidHash : NULL, url, urlLen, cryptogram, &cryptogramLen, verbose); readerErr = VASReader(passTypeIdLen > 0 ? pidHash : NULL, url, urlLen, cryptogram, &cryptogramLen, verbose);
if (readerErr == 0 || kbd_enter_pressed()) { if (readerErr == 0 || kbd_enter_pressed()) {
break; break;
} }
msleep(200);
} while (continuous);
if (readerErr) { msleep(200);
CLIParserFree(ctx); } while (continuous);
mbedtls_ecp_keypair_free(&privKey);
return PM3_EINVARG;
}
uint8_t message[64] = {0}; if (readerErr) {
size_t messageLen = 0; CLIParserFree(ctx);
uint32_t timestamp = 0; mbedtls_ecp_keypair_free(&privKey);
return PM3_EINVARG;
}
if (DecryptVASCryptogram(pidHash, cryptogram, cryptogramLen, &privKey, message, &messageLen, &timestamp) != PM3_SUCCESS) { uint8_t message[64] = {0};
CLIParserFree(ctx); size_t messageLen = 0;
mbedtls_ecp_keypair_free(&privKey); uint32_t timestamp = 0;
return PM3_EINVARG;
}
PrintAndLogEx(SUCCESS, "Message: %s", sprint_ascii(message, messageLen)); if (DecryptVASCryptogram(pidHash, cryptogram, cryptogramLen, &privKey, message, &messageLen, &timestamp) != PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "Timestamp: %d (secs since Jan 1, 2001)", timestamp); CLIParserFree(ctx);
mbedtls_ecp_keypair_free(&privKey);
return PM3_EINVARG;
}
CLIParserFree(ctx); PrintAndLogEx(SUCCESS, "Message: %s", sprint_ascii(message, messageLen));
mbedtls_ecp_keypair_free(&privKey); PrintAndLogEx(SUCCESS, "Timestamp: %d (secs since Jan 1, 2001)", timestamp);
return PM3_SUCCESS;
CLIParserFree(ctx);
mbedtls_ecp_keypair_free(&privKey);
return PM3_SUCCESS;
} }
static int CmdVASDecrypt(const char *Cmd) { static int CmdVASDecrypt(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "nfc vas decrypt", CLIParserInit(&ctx, "nfc vas decrypt",
"Decrypt a previously captured cryptogram", "Decrypt a previously captured cryptogram",
"nfc vas reader -p pass.com.example.ticket -k ./priv.key -> select pass and decrypt with priv.key\nnfc vas reader --url https://example.com -> URL Only mode"); "nfc vas reader -p pass.com.example.ticket -k ./priv.key -> select pass and decrypt with priv.key\nnfc vas reader --url https://example.com -> URL Only mode");
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_str0("p", NULL, "<pid>", "pass type id"), arg_str0("p", NULL, "<pid>", "pass type id"),
arg_str0("k", NULL, "<key>", "path to terminal private key"), arg_str0("k", NULL, "<key>", "path to terminal private key"),
arg_str0(NULL, NULL, "<hex>", "cryptogram to decrypt"), arg_str0(NULL, NULL, "<hex>", "cryptogram to decrypt"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
struct arg_str *passTypeIdArg = arg_get_str(ctx, 1); struct arg_str *passTypeIdArg = arg_get_str(ctx, 1);
int passTypeIdLen = arg_get_str_len(ctx, 1); int passTypeIdLen = arg_get_str_len(ctx, 1);
uint8_t pidHash[32] = {0}; uint8_t pidHash[32] = {0};
sha256hash((uint8_t *) passTypeIdArg->sval[0], passTypeIdLen, pidHash); sha256hash((uint8_t *) passTypeIdArg->sval[0], passTypeIdLen, pidHash);
uint8_t cryptogram[120] = {0}; uint8_t cryptogram[120] = {0};
int cryptogramLen = 0; int cryptogramLen = 0;
CLIGetHexWithReturn(ctx, 3, cryptogram, &cryptogramLen); CLIGetHexWithReturn(ctx, 3, cryptogram, &cryptogramLen);
struct arg_str *keyPathArg = arg_get_str(ctx, 2); struct arg_str *keyPathArg = arg_get_str(ctx, 2);
int keyPathLen = arg_get_str_len(ctx, 2); int keyPathLen = arg_get_str_len(ctx, 2);
if (keyPathLen == 0 && passTypeIdLen > 0) { if (keyPathLen == 0 && passTypeIdLen > 0) {
PrintAndLogEx(FAILED, "Must provide path to terminal private key if a pass type id is provided"); PrintAndLogEx(FAILED, "Must provide path to terminal private key if a pass type id is provided");
CLIParserFree(ctx); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
uint8_t *keyData = NULL; uint8_t *keyData = NULL;
size_t keyDataLen = 0; size_t keyDataLen = 0;
if (loadFile_safe(keyPathArg->sval[0], "", (void **)&keyData, &keyDataLen) != PM3_SUCCESS) { if (loadFile_safe(keyPathArg->sval[0], "", (void **)&keyData, &keyDataLen) != PM3_SUCCESS) {
CLIParserFree(ctx); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
mbedtls_ecp_keypair privKey; mbedtls_ecp_keypair privKey;
mbedtls_ecp_keypair_init(&privKey); mbedtls_ecp_keypair_init(&privKey);
if (LoadReaderPrivateKey(keyData, keyDataLen, &privKey) != PM3_SUCCESS) { if (LoadReaderPrivateKey(keyData, keyDataLen, &privKey) != PM3_SUCCESS) {
CLIParserFree(ctx); CLIParserFree(ctx);
mbedtls_ecp_keypair_free(&privKey); mbedtls_ecp_keypair_free(&privKey);
return PM3_EINVARG; return PM3_EINVARG;
} }
free(keyData); free(keyData);
uint8_t message[64] = {0}; uint8_t message[64] = {0};
size_t messageLen = 0; size_t messageLen = 0;
uint32_t timestamp = 0; uint32_t timestamp = 0;
if (DecryptVASCryptogram(pidHash, cryptogram, cryptogramLen, &privKey, message, &messageLen, &timestamp) != PM3_SUCCESS) { if (DecryptVASCryptogram(pidHash, cryptogram, cryptogramLen, &privKey, message, &messageLen, &timestamp) != PM3_SUCCESS) {
CLIParserFree(ctx); CLIParserFree(ctx);
mbedtls_ecp_keypair_free(&privKey); mbedtls_ecp_keypair_free(&privKey);
return PM3_EINVARG; return PM3_EINVARG;
} }
PrintAndLogEx(SUCCESS, "Message: %s", sprint_ascii(message, messageLen)); PrintAndLogEx(SUCCESS, "Message: %s", sprint_ascii(message, messageLen));
PrintAndLogEx(SUCCESS, "Timestamp: %d (secs since Jan 1, 2001)", timestamp); PrintAndLogEx(SUCCESS, "Timestamp: %d (secs since Jan 1, 2001)", timestamp);
CLIParserFree(ctx); CLIParserFree(ctx);
mbedtls_ecp_keypair_free(&privKey); mbedtls_ecp_keypair_free(&privKey);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
static command_t CommandTable[] = { static command_t CommandTable[] = {
{"--------", CmdHelp, AlwaysAvailable, "----------- " _CYAN_("Value Added Service") " -----------"}, {"--------", CmdHelp, AlwaysAvailable, "----------- " _CYAN_("Value Added Service") " -----------"},
{"reader", CmdVASReader, IfPm3Iso14443a, "Read and decrypt VAS message"}, {"reader", CmdVASReader, IfPm3Iso14443a, "Read and decrypt VAS message"},
{"decrypt", CmdVASDecrypt, AlwaysAvailable, "Decrypt a previously captured VAS cryptogram"}, {"decrypt", CmdVASDecrypt, AlwaysAvailable, "Decrypt a previously captured VAS cryptogram"},
{"--------", CmdHelp, AlwaysAvailable, "----------------- " _CYAN_("General") " -----------------"}, {"--------", CmdHelp, AlwaysAvailable, "----------------- " _CYAN_("General") " -----------------"},
{"help", CmdHelp, AlwaysAvailable, "This help"}, {"help", CmdHelp, AlwaysAvailable, "This help"},
{NULL, NULL, NULL, NULL} {NULL, NULL, NULL, NULL}
}; };
int CmdVAS(const char *Cmd) { int CmdVAS(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
return CmdsParse(CommandTable, Cmd); return CmdsParse(CommandTable, Cmd);
}; };
static int CmdHelp(const char *Cmd) { static int CmdHelp(const char *Cmd) {
(void)Cmd; // Cmd is not used so far (void)Cmd; // Cmd is not used so far
CmdsHelp(CommandTable); CmdsHelp(CommandTable);
return PM3_SUCCESS; return PM3_SUCCESS;
}; };

View file

@ -638,31 +638,31 @@ int blowfish_decrypt(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output,
// Implementation from http://www.secg.org/sec1-v2.pdf#subsubsection.3.6.1 // Implementation from http://www.secg.org/sec1-v2.pdf#subsubsection.3.6.1
int ansi_x963_sha256(uint8_t *sharedSecret, size_t sharedSecretLen, uint8_t *sharedInfo, size_t sharedInfoLen, size_t keyDataLen, uint8_t *keyData) { int ansi_x963_sha256(uint8_t *sharedSecret, size_t sharedSecretLen, uint8_t *sharedInfo, size_t sharedInfoLen, size_t keyDataLen, uint8_t *keyData) {
// sha256 hash has (practically) no max input len, so skipping that step // sha256 hash has (practically) no max input len, so skipping that step
if (keyDataLen >= 32 * (pow(2, 32) - 1)) { if (keyDataLen >= 32 * (pow(2, 32) - 1)) {
return 1; return 1;
} }
uint32_t counter = 0x00000001; uint32_t counter = 0x00000001;
for (int i = 0; i < (keyDataLen / 32); ++i) { for (int i = 0; i < (keyDataLen / 32); ++i) {
uint8_t *hashMaterial = malloc(4 + sharedSecretLen + sharedInfoLen); uint8_t *hashMaterial = malloc(4 + sharedSecretLen + sharedInfoLen);
memcpy(hashMaterial, sharedSecret, sharedSecretLen); memcpy(hashMaterial, sharedSecret, sharedSecretLen);
hashMaterial[sharedSecretLen] = (counter >> 24); hashMaterial[sharedSecretLen] = (counter >> 24);
hashMaterial[sharedSecretLen + 1] = (counter >> 16) & 0xFF; hashMaterial[sharedSecretLen + 1] = (counter >> 16) & 0xFF;
hashMaterial[sharedSecretLen + 2] = (counter >> 8) & 0xFF; hashMaterial[sharedSecretLen + 2] = (counter >> 8) & 0xFF;
hashMaterial[sharedSecretLen + 3] = counter & 0xFF; hashMaterial[sharedSecretLen + 3] = counter & 0xFF;
memcpy(hashMaterial + sharedSecretLen + 4, sharedInfo, sharedInfoLen); memcpy(hashMaterial + sharedSecretLen + 4, sharedInfo, sharedInfoLen);
uint8_t hash[32] = {0}; uint8_t hash[32] = {0};
sha256hash(hashMaterial, 4 + sharedSecretLen + sharedInfoLen, hash); sha256hash(hashMaterial, 4 + sharedSecretLen + sharedInfoLen, hash);
free(hashMaterial); free(hashMaterial);
memcpy(keyData + (32 * i), hash, 32); memcpy(keyData + (32 * i), hash, 32);
counter++; counter++;
} }
return 0; return 0;
} }

View file

@ -1,5 +1,5 @@
/* /*
* Not original to the mbedtls library. Taken from * Not original to the mbedtls library. Taken from
* https://github.com/mwarning/mbedtls_ecp_compression * https://github.com/mwarning/mbedtls_ecp_compression
* to solve mbedtls' lack of support for elliptic point * to solve mbedtls' lack of support for elliptic point
* compression and decompression * compression and decompression
@ -35,13 +35,13 @@ int mbedtls_ecp_decompress(
*olen = 2 * plen + 1; *olen = 2 * plen + 1;
if (osize < *olen) if (osize < *olen)
return(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL); return (MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL);
if (ilen != plen + 1) if (ilen != plen + 1)
return(MBEDTLS_ERR_ECP_BAD_INPUT_DATA); return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA);
if (input[0] != 0x02 && input[0] != 0x03) if (input[0] != 0x02 && input[0] != 0x03)
return(MBEDTLS_ERR_ECP_BAD_INPUT_DATA); return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA);
// output will consist of 0x04|X|Y // output will consist of 0x04|X|Y
memcpy(output, input, ilen); memcpy(output, input, ilen);
@ -97,7 +97,7 @@ cleanup:
mbedtls_mpi_free(&x); mbedtls_mpi_free(&x);
mbedtls_mpi_free(&n); mbedtls_mpi_free(&n);
return(ret); return (ret);
} }
int mbedtls_ecp_compress( int mbedtls_ecp_compress(
@ -112,13 +112,13 @@ int mbedtls_ecp_compress(
*olen = plen + 1; *olen = plen + 1;
if (osize < *olen) if (osize < *olen)
return(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL); return (MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL);
if (ilen != 2 * plen + 1) if (ilen != 2 * plen + 1)
return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA); return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA);
if (input[0] != 0x04) if (input[0] != 0x04)
return(MBEDTLS_ERR_ECP_BAD_INPUT_DATA); return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA);
// output will consist of 0x0?|X // output will consist of 0x0?|X
memcpy(output, input, *olen); memcpy(output, input, *olen);
@ -126,5 +126,5 @@ int mbedtls_ecp_compress(
// Encode even/odd of Y into first byte (either 0x02 or 0x03) // Encode even/odd of Y into first byte (either 0x02 or 0x03)
output[0] = 0x02 + (input[2 * plen] & 1); output[0] = 0x02 + (input[2 * plen] & 1);
return(0); return (0);
} }

View file

@ -1,5 +1,5 @@
/* /*
* Not original to the mbedtls library. Taken from * Not original to the mbedtls library. Taken from
* https://github.com/mwarning/mbedtls_ecp_compression * https://github.com/mwarning/mbedtls_ecp_compression
* to solve mbedtls' lack of support for elliptic point * to solve mbedtls' lack of support for elliptic point
* compression and decompression * compression and decompression