1 // Copyright 2017 Google Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 //////////////////////////////////////////////////////////////////////////////// 16 17 package com.google.crypto.tink.hybrid; 18 19 import com.google.crypto.tink.Aead; 20 import com.google.crypto.tink.DeterministicAead; 21 import com.google.crypto.tink.Registry; 22 import com.google.crypto.tink.aead.AeadConfig; 23 import com.google.crypto.tink.daead.DeterministicAeadConfig; 24 import com.google.crypto.tink.hybrid.subtle.AeadOrDaead; 25 import com.google.crypto.tink.proto.AesCtrHmacAeadKey; 26 import com.google.crypto.tink.proto.AesCtrHmacAeadKeyFormat; 27 import com.google.crypto.tink.proto.AesCtrKey; 28 import com.google.crypto.tink.proto.AesGcmKey; 29 import com.google.crypto.tink.proto.AesGcmKeyFormat; 30 import com.google.crypto.tink.proto.AesSivKey; 31 import com.google.crypto.tink.proto.AesSivKeyFormat; 32 import com.google.crypto.tink.proto.HmacKey; 33 import com.google.crypto.tink.proto.KeyTemplate; 34 import com.google.crypto.tink.subtle.EciesAeadHkdfDemHelper; 35 import com.google.protobuf.ByteString; 36 import com.google.protobuf.ExtensionRegistryLite; 37 import com.google.protobuf.InvalidProtocolBufferException; 38 import java.security.GeneralSecurityException; 39 import java.util.Arrays; 40 41 /** 42 * Helper generating {@code Aead}-instances for specified {@code KeyTemplate} and key material. It 43 * uses selected {@code KeyManager}-instances from the {@code Registry} to obtain the instances of 44 * {@code Aead}. 45 */ 46 class RegistryEciesAeadHkdfDemHelper implements EciesAeadHkdfDemHelper { 47 private final String demKeyTypeUrl; 48 private final int symmetricKeySize; 49 50 // used iff demKeyTypeUrl == AeadConfig.AES_GCM_TYPE_URL 51 private AesGcmKey aesGcmKey; 52 53 // used iff demKeyTypeUrl == AeadConfig.AES_CTR_HMAC_AEAD_TYPE_URL 54 private AesCtrHmacAeadKey aesCtrHmacAeadKey; 55 private int aesCtrKeySize; 56 57 // used iff demKeyTypeUrl == AeadConfig.AES_SIV_TYPE_URL 58 private AesSivKey aesSivKey; 59 RegistryEciesAeadHkdfDemHelper(KeyTemplate demTemplate)60 RegistryEciesAeadHkdfDemHelper(KeyTemplate demTemplate) throws GeneralSecurityException { 61 demKeyTypeUrl = demTemplate.getTypeUrl(); 62 if (demKeyTypeUrl.equals(AeadConfig.AES_GCM_TYPE_URL)) { 63 try { 64 AesGcmKeyFormat gcmKeyFormat = 65 AesGcmKeyFormat.parseFrom( 66 demTemplate.getValue(), ExtensionRegistryLite.getEmptyRegistry()); 67 this.aesGcmKey = 68 AesGcmKey.parseFrom( 69 Registry.newKeyData(demTemplate).getValue(), 70 ExtensionRegistryLite.getEmptyRegistry()); 71 this.symmetricKeySize = gcmKeyFormat.getKeySize(); 72 } catch (InvalidProtocolBufferException e) { 73 throw new GeneralSecurityException( 74 "invalid KeyFormat protobuf, expected AesGcmKeyFormat", e); 75 } 76 } else if (demKeyTypeUrl.equals(AeadConfig.AES_CTR_HMAC_AEAD_TYPE_URL)) { 77 try { 78 AesCtrHmacAeadKeyFormat aesCtrHmacAeadKeyFormat = 79 AesCtrHmacAeadKeyFormat.parseFrom( 80 demTemplate.getValue(), ExtensionRegistryLite.getEmptyRegistry()); 81 this.aesCtrHmacAeadKey = 82 AesCtrHmacAeadKey.parseFrom( 83 Registry.newKeyData(demTemplate).getValue(), 84 ExtensionRegistryLite.getEmptyRegistry()); 85 this.aesCtrKeySize = aesCtrHmacAeadKeyFormat.getAesCtrKeyFormat().getKeySize(); 86 int hmacKeySize = aesCtrHmacAeadKeyFormat.getHmacKeyFormat().getKeySize(); 87 this.symmetricKeySize = aesCtrKeySize + hmacKeySize; 88 } catch (InvalidProtocolBufferException e) { 89 throw new GeneralSecurityException( 90 "invalid KeyFormat protobuf, expected AesCtrHmacAeadKeyFormat", e); 91 } 92 } else if (demKeyTypeUrl.equals(DeterministicAeadConfig.AES_SIV_TYPE_URL)) { 93 try { 94 AesSivKeyFormat aesSivKeyFormat = 95 AesSivKeyFormat.parseFrom( 96 demTemplate.getValue(), ExtensionRegistryLite.getEmptyRegistry()); 97 this.aesSivKey = 98 AesSivKey.parseFrom( 99 Registry.newKeyData(demTemplate).getValue(), 100 ExtensionRegistryLite.getEmptyRegistry()); 101 this.symmetricKeySize = aesSivKeyFormat.getKeySize(); 102 } catch (InvalidProtocolBufferException e) { 103 throw new GeneralSecurityException( 104 "invalid KeyFormat protobuf, expected AesCtrHmacAeadKeyFormat", e); 105 } 106 } else { 107 throw new GeneralSecurityException("unsupported AEAD DEM key type: " + demKeyTypeUrl); 108 } 109 } 110 111 @Override getSymmetricKeySizeInBytes()112 public int getSymmetricKeySizeInBytes() { 113 return symmetricKeySize; 114 } 115 116 @Override getAeadOrDaead(final byte[] symmetricKeyValue)117 public AeadOrDaead getAeadOrDaead(final byte[] symmetricKeyValue) 118 throws GeneralSecurityException { 119 if (symmetricKeyValue.length != getSymmetricKeySizeInBytes()) { 120 throw new GeneralSecurityException("Symmetric key has incorrect length"); 121 } 122 if (demKeyTypeUrl.equals(AeadConfig.AES_GCM_TYPE_URL)) { 123 AesGcmKey aeadKey = AesGcmKey.newBuilder() 124 .mergeFrom(aesGcmKey) 125 .setKeyValue(ByteString.copyFrom(symmetricKeyValue, 0, symmetricKeySize)) 126 .build(); 127 return new AeadOrDaead( 128 Registry.getPrimitive(demKeyTypeUrl, aeadKey.toByteString(), Aead.class)); 129 } else if (demKeyTypeUrl.equals(AeadConfig.AES_CTR_HMAC_AEAD_TYPE_URL)) { 130 byte[] aesCtrKeyValue = Arrays.copyOfRange(symmetricKeyValue, 0, aesCtrKeySize); 131 byte[] hmacKeyValue = Arrays.copyOfRange(symmetricKeyValue, aesCtrKeySize, symmetricKeySize); 132 AesCtrKey aesCtrKey = 133 AesCtrKey.newBuilder() 134 .mergeFrom(aesCtrHmacAeadKey.getAesCtrKey()) 135 .setKeyValue(ByteString.copyFrom(aesCtrKeyValue)) 136 .build(); 137 HmacKey hmacKey = 138 HmacKey.newBuilder() 139 .mergeFrom(aesCtrHmacAeadKey.getHmacKey()) 140 .setKeyValue(ByteString.copyFrom(hmacKeyValue)) 141 .build(); 142 AesCtrHmacAeadKey aeadKey = 143 AesCtrHmacAeadKey.newBuilder() 144 .setVersion(aesCtrHmacAeadKey.getVersion()) 145 .setAesCtrKey(aesCtrKey) 146 .setHmacKey(hmacKey) 147 .build(); 148 return new AeadOrDaead( 149 Registry.getPrimitive(demKeyTypeUrl, aeadKey.toByteString(), Aead.class)); 150 } else if (demKeyTypeUrl.equals(DeterministicAeadConfig.AES_SIV_TYPE_URL)) { 151 AesSivKey daeadKey = 152 AesSivKey.newBuilder() 153 .mergeFrom(aesSivKey) 154 .setKeyValue(ByteString.copyFrom(symmetricKeyValue, 0, symmetricKeySize)) 155 .build(); 156 return new AeadOrDaead( 157 Registry.getPrimitive(demKeyTypeUrl, daeadKey.toByteString(), DeterministicAead.class)); 158 } else { 159 throw new GeneralSecurityException("unknown DEM key type"); 160 } 161 } 162 } 163