private static void doDecrypt(EncryptedContent content, Blob ckBits, DecryptorV2.DecryptSuccessCallback onSuccess_0, EncryptError.OnError onError_1) { if (!content.hasInitialVector()) { onError_1.onError( net.named_data.jndn.encrypt.EncryptError.ErrorCode.MissingRequiredInitialVector, "Expecting Initial Vector in the encrypted content, but it is not present"); return; } Blob plainData; try { Cipher cipher = javax.crypto.Cipher.getInstance("AES/CBC/PKCS5PADDING"); cipher.init(javax.crypto.Cipher.DECRYPT_MODE, new SecretKeySpec(ckBits.getImmutableArray(), "AES"), new IvParameterSpec(content.getInitialVector() .getImmutableArray())); plainData = new Blob(cipher.doFinal(content.getPayload() .getImmutableArray()), false); } catch (Exception ex) { onError_1.onError(net.named_data.jndn.encrypt.EncryptError.ErrorCode.DecryptionFailure, "Decryption error in doDecrypt: " + ex); return; } try { onSuccess_0.onSuccess(plainData); } catch (Exception exception) { logger_.log(ILOG.J2CsMapping.Util.Logging.Level.SEVERE, "Error in onSuccess", exception); } }
/// <returns>True for success, false for error (where this has called onError).</returns> internal bool decryptAndImportKdk(Data kdkData, EncryptError.OnError onError_0) { try { logger_.log(ILOG.J2CsMapping.Util.Logging.Level.INFO, "Decrypting and importing KDK {0}", kdkData.getName()); EncryptedContent encryptedContent_1 = new EncryptedContent(); encryptedContent_1.wireDecodeV2(kdkData.getContent()); SafeBag safeBag = new SafeBag(encryptedContent_1.getPayload()); Blob secret = keyChain_.getTpm().decrypt( encryptedContent_1.getPayloadKey().buf(), credentialsKey_.getName()); if (secret.isNull()) { onError_0.onError(net.named_data.jndn.encrypt.EncryptError.ErrorCode.TpmKeyNotFound, "Could not decrypt secret, " + credentialsKey_.getName().toUri() + " not found in TPM"); return(false); } internalKeyChain_.importSafeBag(safeBag, secret.buf()); return(true); } catch (Exception ex) { // This can be EncodingException, Pib.Error, Tpm.Error, or a bunch of // other runtime-derived errors. onError_0.onError(net.named_data.jndn.encrypt.EncryptError.ErrorCode.DecryptionFailure, "Failed to decrypt KDK [" + kdkData.getName().toUri() + "]: " + ex); return(false); } }
/// <summary> /// Asynchronously decrypt the encryptedContent. /// </summary> /// /// <param name="encryptedContent">the EncryptedContent object. If you may change it later, then pass in a copy of the object.</param> /// <param name="onSuccess">NOTE: The library will log any exceptions thrown by this callback, but for better error handling the callback should catch and properly handle any exceptions.</param> /// <param name="onError_0">error string. NOTE: The library will log any exceptions thrown by this callback, but for better error handling the callback should catch and properly handle any exceptions.</param> public void decrypt(EncryptedContent encryptedContent, DecryptorV2.DecryptSuccessCallback onSuccess, EncryptError.OnError onError_0) { if (encryptedContent.getKeyLocator().getType() != net.named_data.jndn.KeyLocatorType.KEYNAME) { logger_.log(ILOG.J2CsMapping.Util.Logging.Level.INFO, "Missing required KeyLocator in the supplied EncryptedContent block"); onError_0.onError(net.named_data.jndn.encrypt.EncryptError.ErrorCode.MissingRequiredKeyLocator, "Missing required KeyLocator in the supplied EncryptedContent block"); return; } if (!encryptedContent.hasInitialVector()) { logger_.log(ILOG.J2CsMapping.Util.Logging.Level.INFO, "Missing required initial vector in the supplied EncryptedContent block"); onError_0.onError( net.named_data.jndn.encrypt.EncryptError.ErrorCode.MissingRequiredInitialVector, "Missing required initial vector in the supplied EncryptedContent block"); return; } Name ckName_1 = encryptedContent.getKeyLocatorName(); DecryptorV2.ContentKey contentKey_2 = ILOG.J2CsMapping.Collections.Collections.Get(contentKeys_, ckName_1); bool isNew = (contentKey_2 == null); if (isNew) { contentKey_2 = new DecryptorV2.ContentKey(); ILOG.J2CsMapping.Collections.Collections.Put(contentKeys_, ckName_1, contentKey_2); } if (contentKey_2.isRetrieved) { doDecrypt(encryptedContent, contentKey_2.bits, onSuccess, onError_0); } else { logger_.log( ILOG.J2CsMapping.Util.Logging.Level.INFO, "CK {0} not yet available, so adding to the pending decrypt queue", ckName_1); ILOG.J2CsMapping.Collections.Collections.Add(contentKey_2.pendingDecrypts, new ContentKey.PendingDecrypt( encryptedContent, onSuccess, onError_0)); } if (isNew) { fetchCk(ckName_1, contentKey_2, onError_0, net.named_data.jndn.encrypt.EncryptorV2.N_RETRIES); } }
internal void decryptCkAndProcessPendingDecrypts(DecryptorV2.ContentKey contentKey_0, Data ckData_1, Name kdkKeyName, EncryptError.OnError onError_2) { logger_.log(ILOG.J2CsMapping.Util.Logging.Level.INFO, "Decrypting CK data {0}", ckData_1.getName()); EncryptedContent content = new EncryptedContent(); try { content.wireDecodeV2(ckData_1.getContent()); } catch (Exception ex) { onError_2.onError(net.named_data.jndn.encrypt.EncryptError.ErrorCode.InvalidEncryptedFormat, "Error decrypting EncryptedContent: " + ex); return; } Blob ckBits; try { ckBits = internalKeyChain_.getTpm().decrypt( content.getPayload().buf(), kdkKeyName); } catch (Exception ex_3) { // We don't expect this from the in-memory KeyChain. onError_2.onError(net.named_data.jndn.encrypt.EncryptError.ErrorCode.DecryptionFailure, "Error decrypting the CK EncryptedContent " + ex_3); return; } if (ckBits.isNull()) { onError_2.onError(net.named_data.jndn.encrypt.EncryptError.ErrorCode.TpmKeyNotFound, "Could not decrypt secret, " + kdkKeyName.toUri() + " not found in TPM"); return; } contentKey_0.bits = ckBits; contentKey_0.isRetrieved = true; /* foreach */ foreach (ContentKey.PendingDecrypt pendingDecrypt in contentKey_0.pendingDecrypts) { // TODO: If this calls onError, should we quit? doDecrypt(pendingDecrypt.encryptedContent, contentKey_0.bits, pendingDecrypt.onSuccess, pendingDecrypt.onError); } ILOG.J2CsMapping.Collections.Collections.Clear(contentKey_0.pendingDecrypts); }
/// <summary> /// Extract the KDK information from the CK Data packet name. The KDK identity name /// plus the KDK key ID together identify the KDK private key in the KeyChain. /// </summary> /// /// <param name="ckDataName">The name of the CK Data packet.</param> /// <param name="ckName_0">The CK name from the Interest used to fetch the CK Data packet.</param> /// <param name="onError_1">This calls onError.onError(errorCode, message) for an error.</param> /// <param name="kdkPrefix_2">This sets kdkPrefix[0] to the KDK prefix.</param> /// <param name="kdkIdentityName">This sets kdkIdentityName[0] to the KDK identity name.</param> /// <param name="kdkKeyId">This sets kdkKeyId[0] to the KDK key ID.</param> /// <returns>True for success or false if an error was reported to onError.</returns> static internal bool extractKdkInfoFromCkName(Name ckDataName, Name ckName_0, EncryptError.OnError onError_1, Name[] kdkPrefix_2, Name[] kdkIdentityName, Name[] kdkKeyId) { // <full-ck-name-with-id> | /ENCRYPTED-BY/<kek-prefix>/NAC/KEK/<key-id> if (ckDataName.size() < ckName_0.size() + 1 || !ckDataName.getPrefix(ckName_0.size()).equals(ckName_0) || !ckDataName.get(ckName_0.size()).equals( net.named_data.jndn.encrypt.EncryptorV2.NAME_COMPONENT_ENCRYPTED_BY)) { onError_1.onError(net.named_data.jndn.encrypt.EncryptError.ErrorCode.CkInvalidName, "Invalid CK name [" + ckDataName.toUri() + "]"); return(false); } Name kekName = ckDataName.getSubName(ckName_0.size() + 1); kdkPrefix_2[0] = convertKekNameToKdkPrefix(kekName, onError_1); if (kdkPrefix_2[0] == null) { // The error has already been reported. return(false); } kdkIdentityName[0] = kekName.getPrefix(-2); kdkKeyId[0] = kekName.getPrefix(-2).append("KEY") .append(kekName.get(-1)); return(true); }
internal void fetchKdk(DecryptorV2.ContentKey contentKey_0, Name kdkPrefix_1, Data ckData_2, EncryptError.OnError onError_3, int nTriesLeft_4) { // <kdk-prefix>/KDK/<kdk-id> /ENCRYPTED-BY /<credential-identity>/KEY/<key-id> // \ / \ / // ----------- ------------- --------------- --------------- // \/ \/ // from the CK data from configuration Name kdkName = new Name(kdkPrefix_1); kdkName.append(net.named_data.jndn.encrypt.EncryptorV2.NAME_COMPONENT_ENCRYPTED_BY).append( credentialsKey_.getName()); logger_.log(ILOG.J2CsMapping.Util.Logging.Level.INFO, "Fetching KDK {0}", kdkName); try { contentKey_0.pendingInterest = face_.expressInterest(new Interest( kdkName).setMustBeFresh(true).setCanBePrefix(false), new DecryptorV2.Anonymous_C2(this, kdkPrefix_1, onError_3, contentKey_0, ckData_2), new DecryptorV2.Anonymous_C1(this, contentKey_0, onError_3, kdkPrefix_1, ckData_2, nTriesLeft_4), new DecryptorV2.Anonymous_C0(contentKey_0, onError_3)); } catch (Exception ex) { onError_3.onError(net.named_data.jndn.encrypt.EncryptError.ErrorCode.General, "expressInterest error: " + ex); } }
/// <summary> /// Convert the KEK name to the KDK prefix: /// <access-namespace>/KEK/<key-id> ==> <access-namespace>/KDK/<key-id>. /// </summary> /// /// <param name="kekName">The KEK name.</param> /// <param name="onError_0">This calls onError.onError(errorCode, message) for an error.</param> /// <returns>The KDK prefix, or null if an error was reported to onError.</returns> private static Name convertKekNameToKdkPrefix(Name kekName, EncryptError.OnError onError_0) { if (kekName.size() < 2 || !kekName.get(-2).equals(net.named_data.jndn.encrypt.EncryptorV2.NAME_COMPONENT_KEK)) { onError_0.onError(net.named_data.jndn.encrypt.EncryptError.ErrorCode.KekInvalidName, "Invalid KEK name [" + kekName.toUri() + "]"); return(null); } return(kekName.getPrefix(-2).append(net.named_data.jndn.encrypt.EncryptorV2.NAME_COMPONENT_KDK) .append(kekName.get(-1))); }
internal void fetchCk(Name ckName_0, DecryptorV2.ContentKey contentKey_1, EncryptError.OnError onError_2, int nTriesLeft_3) { // The full name of the CK is // // <whatever-prefix>/CK/<ck-id> /ENCRYPTED-BY /<kek-prefix>/KEK/<key-id> // \ / \ / // ----------- ------------- ----------- ----------- // \/ \/ // from the encrypted data unknown (name in retrieved CK is used to determine KDK) logger_.log(ILOG.J2CsMapping.Util.Logging.Level.INFO, "Fetching CK {0}", ckName_0); try { contentKey_1.pendingInterest = face_.expressInterest(new Interest( ckName_0).setMustBeFresh(false).setCanBePrefix(true), new DecryptorV2.Anonymous_C5(this, onError_2, contentKey_1), new DecryptorV2.Anonymous_C4(this, onError_2, nTriesLeft_3, contentKey_1, ckName_0), new DecryptorV2.Anonymous_C3(contentKey_1, onError_2)); } catch (Exception ex) { onError_2.onError(net.named_data.jndn.encrypt.EncryptError.ErrorCode.General, "expressInterest error: " + ex); } }