initSession static method
Implementation
static Future<void> initSession(
{required DBAKey dbaKeys, required ICC icc}) async {
_log.debug("🆔 MRZ input for BAC:");
_log.debug(" Passport number: ${dbaKeys.mrtdNumber}");
_log.debug(" Date of birth: ${dbaKeys.dateOfBirth}");
_log.debug(" Expiry date: ${dbaKeys.dateOfExpiry}");
final Kenc = dbaKeys.encKey;
final Kmac = dbaKeys.macKey;
// We don't want to see these data in production logs
_log.sdVerbose("Key seed=${dbaKeys.keySeed.hex()}");
_log.sdVerbose("Derived Kenc=${Kenc.hex()}");
_log.sdVerbose("Derived Kmac=${Kmac.hex()}");
// Get random nonce from ICC
_log.debug("Requesting challenge from ICC");
final RNDicc = await icc.getChallenge(challengeLength: nonceLen);
_log.verbose("Received RND.IC=${RNDicc.hex()}");
// Generate random RND.IFD & K.IFD
final RNDifd = randomBytes(nonceLen);
final Kifd = randomBytes(kLen);
_log.verbose("Generated RND.IFD=${RNDifd.hex()}");
_log.sdVerbose("Generated K.IFD=${Kifd.hex()}");
// Generate S
final S = generateS(RNDicc: RNDicc, RNDifd: RNDifd, Kifd: Kifd);
_log.sdVerbose("Generated S=${S.hex()}");
// Compute cryptogram Eifd and it's mac Mifd
final Eifd = E(Kenc: Kenc, S: S);
final Mifd = MAC(Kmac: Kmac, Eifd: Eifd);
// Execute EXTERNAL AUTHENTICATE command on ICC
_log.debug("Sending EXTERNAL AUTHENTICATE command");
_log.verbose(" Eifd=${Eifd.hex()}");
_log.verbose(" Mifd=${Mifd.hex()}");
final ICCeaData = await icc.externalAuthenticate(
data: generateEAData(Eifd: Eifd, Mifd: Mifd), ne: eLen + macLen);
final pairEiccMicc = extractEiccAndMicc(ICCea_data: ICCeaData);
_log.verbose("Received from ICC:");
_log.verbose(" Eicc=${pairEiccMicc.first.hex()}");
_log.verbose(" Micc=${pairEiccMicc.second.hex()}");
// Verify MAC of received Eicc
if (!verifyEicc(
Eicc: pairEiccMicc.first, Kmac: Kmac, Micc: pairEiccMicc.second)) {
_log.error("Verifying mac of Eicc failed");
throw BACError("Verifying mac of Eicc failed");
}
// Decrypt R from received Eicc
_log.debug("Generating session keys KSenc and KSmac");
final R = D(Kdec: Kenc, Eicc: pairEiccMicc.first);
_log.verbose("Decrypted R=${R.hex()}");
// Verify R contains our RND.IFD and extract Kicc from R
final Kicc = verifyRNDifdAndExtractKicc(RNDifd: RNDifd, R: R);
_log.sdVerbose("K.ICC=${Kicc.hex()}");
// Calculate session keys from Kifd and Kicc
final pairKS = calculateSessionKeys(Kifd: Kifd, Kicc: Kicc);
_log.sdVerbose("Calculated session keys:");
_log.sdVerbose(" KSenc=${pairKS.first.hex()}");
_log.sdVerbose(" KSmac=${pairKS.second.hex()}");
// Calculate SCC from RND.IFD and RND.ICC
final ssc = calculateSCC(RNDifd: RNDifd, RNDicc: RNDicc);
_log.verbose("Calculated SCC=${ssc.toBytes().hex()}");
_log.debug("Finished BAC SM key establishment");
icc.sm = MrtdSM(DES_SMCipher(pairKS.first, pairKS.second), ssc);
_log.debug("SM session is set up");
}