com.amazonaws.encryptionsdk.EncryptedDataKey Maven / Gradle / Ivy
/*
* Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except
* in compliance with the License. A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.amazonaws.encryptionsdk;
//@ model import java.util.Arrays;
//@ model import java.nio.charset.StandardCharsets;
//@ nullable_by_default
public interface EncryptedDataKey {
//@// An EncryptedDataKey object abstractly contains 3 pieces of data.
//@// These are represented by 3 byte arrays:
//@ model public instance byte[] providerId;
//@ model public instance byte[] providerInformation;
//@ model public instance byte[] encryptedDataKey;
//@// The fields of an EncryptedDataKey may be populated via deserialization. The
//@// Encryption SDK design allows the deserialization routine to be called repeatedly,
//@// each call trying to fill in information that for some reason was not possible
//@// with the previous call. In some such "intermediate" states, the deserialization
//@// is incomplete in a way that other methods don't expect. Therefore, those methods
//@// should not be called in these incomplete intermediate states. The model field
//@// isDeserializing is true in those incomplete intermediate states, and it is used
//@// in method specifications.
//@ public model instance boolean isDeserializing;
//@// There are some complications surrounding the representations of strings versus
//@// byte arrays. The serialized form in message headers is always a sequence of
//@// bytes, but the EncryptedDataKey interface (and some other methods)
//@// expose the provider ID as if it were a string. Conversions (using UTF-8)
//@// between byte arrays and strings (which in Java use UTF-16) are not bijections.
//@// For example, both "\u003f".getBytes() and "\ud800".getBytes() yield a 1-byte
//@// array containing [0x3f], and calling `new String(..., StandardCharsets.UTF_8)`
//@// with either the 1-byte array [0x80] or the 3-byte array [0xef,0xbf,0xbd] yields
//@// the string "\ufffd". Therefore, all we can say about these conversions
//@// is that a given byte[]-String pair satisfies a conversion relation.
//@//
//@// The model functions "ba2s" and "s2ba" are used to specify the conversions
//@// between byte arrays and strings:
/*@ public normal_behavior
@ requires s != null;
@ ensures \result != null;
@ function
@ public model static byte[] s2ba(String s) {
@ return s.getBytes(StandardCharsets.UTF_8);
@ }
@*/
/*@ public normal_behavior
@ requires ba != null;
@ ensures \result != null;
@ function
@ public model static String ba2s(byte[] ba) {
@ return new String(ba, StandardCharsets.UTF_8);
@ }
@*/
//@// The "ba2s" and "s2ba" are given function bodies above, but the verification
//@// does not rely on these function bodies directly. Instead, the code (in KeyBlob)
//@// uses "assume" statements when it necessary to connect these functions with
//@// copies of their bodies that appear in the code. This is a limitation of JML.
//@//
//@// One of the properties that holds of "s2ba(s)" is that its result depends not
//@// on the particular String reference "s" being passed in, but only the contents
//@// of the string referenced by "s". This property is captured in the following
//@// lemma:
/*@ public normal_behavior
@ requires s != null && t != null && String.equals(s, t);
@ ensures Arrays.equalArrays(s2ba(s), s2ba(t));
@ pure
@ public model static void lemma_s2ba_depends_only_string_contents_only(String s, String t);
@*/
//@//
//@// As a specification convenience, the model function "ba2s2ba" uses the two
//@// model functions above to convert from a byte array to a String and then back
//@// to a byte array. As mentioned above, this does not always result in a byte
//@// array with the original contents. The "assume" statements about the conversion
//@// functions need to be careful not to assume too much.
/*@ public normal_behavior
@ requires ba != null;
@ ensures \result == s2ba(ba2s(ba));
@ function
@ public model static byte[] ba2s2ba(byte[] ba) {
@ return s2ba(ba2s(ba));
@ }
@*/
//@// Here follows 3 methods that access the abstract values of interface properties.
//@// Something to note about these methods is that each one requires the property
//@// requested to be known to be non-null. For example, "getProviderId" is only allowed
//@// to be called when "providerId" is known to be non-null.
//@ public normal_behavior
//@ requires providerId != null;
//@ ensures \result != null;
//@ ensures String.equals(\result, ba2s(providerId));
//@ pure
public String getProviderId();
//@ public normal_behavior
//@ requires providerInformation != null;
//@ ensures \fresh(\result);
//@ ensures Arrays.equalArrays(providerInformation, \result);
//@ pure
public byte[] getProviderInformation();
//@ public normal_behavior
//@ requires encryptedDataKey != null;
//@ ensures \fresh(\result);
//@ ensures Arrays.equalArrays(encryptedDataKey, \result);
//@ pure
public byte[] getEncryptedDataKey();
}