This commit is contained in:
Phil Race 2018-07-19 10:17:22 -07:00
commit 28e828130d
129 changed files with 2316 additions and 591 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -29,6 +29,8 @@
package com.sun.crypto.provider;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import javax.crypto.IllegalBlockSizeException;
import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE;
@ -68,6 +70,15 @@ final class GCTR extends CounterMode {
return "GCTR";
}
// return the number of blocks until the lower 32 bits roll over
private long blocksUntilRollover() {
ByteBuffer buf = ByteBuffer.wrap(counter, counter.length - 4, 4);
buf.order(ByteOrder.BIG_ENDIAN);
long ctr32 = 0xFFFFFFFFL & buf.getInt();
long blocksLeft = (1L << 32) - ctr32;
return blocksLeft;
}
// input must be multiples of 128-bit blocks when calling update
int update(byte[] in, int inOfs, int inLen, byte[] out, int outOfs) {
if (inLen - inOfs > in.length) {
@ -80,7 +91,25 @@ final class GCTR extends CounterMode {
throw new RuntimeException("output buffer too small");
}
return encrypt(in, inOfs, inLen, out, outOfs);
long blocksLeft = blocksUntilRollover();
int numOfCompleteBlocks = inLen / AES_BLOCK_SIZE;
if (numOfCompleteBlocks >= blocksLeft) {
// Counter Mode encryption cannot be used because counter will
// roll over incorrectly. Use GCM-specific code instead.
byte[] encryptedCntr = new byte[AES_BLOCK_SIZE];
for (int i = 0; i < numOfCompleteBlocks; i++) {
embeddedCipher.encryptBlock(counter, 0, encryptedCntr, 0);
for (int n = 0; n < AES_BLOCK_SIZE; n++) {
int index = (i * AES_BLOCK_SIZE + n);
out[outOfs + index] =
(byte) ((in[inOfs + index] ^ encryptedCntr[n]));
}
GaloisCounterMode.increment32(counter);
}
return inLen;
} else {
return encrypt(in, inOfs, inLen, out, outOfs);
}
}
// input can be arbitrary size when calling doFinal

View file

@ -33,7 +33,6 @@ import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEParameterSpec;
import sun.security.util.HexDumpEncoder;
import sun.security.util.*;
/**
@ -260,21 +259,7 @@ abstract class PBES2Parameters extends AlgorithmParametersSpi {
String kdfAlgo = null;
String cipherAlgo = null;
DerValue pBES2Algorithms = new DerValue(encoded);
if (pBES2Algorithms.tag != DerValue.tag_Sequence) {
throw new IOException("PBE parameter parsing error: "
+ "not an ASN.1 SEQUENCE tag");
}
if (!pkcs5PBES2_OID.equals(pBES2Algorithms.data.getOID())) {
throw new IOException("PBE parameter parsing error: "
+ "expecting the object identifier for PBES2");
}
if (pBES2Algorithms.tag != DerValue.tag_Sequence) {
throw new IOException("PBE parameter parsing error: "
+ "not an ASN.1 SEQUENCE tag");
}
DerValue pBES2_params = pBES2Algorithms.data.getDerValue();
DerValue pBES2_params = new DerValue(encoded);
if (pBES2_params.tag != DerValue.tag_Sequence) {
throw new IOException("PBE parameter parsing error: "
+ "not an ASN.1 SEQUENCE tag");
@ -293,7 +278,6 @@ abstract class PBES2Parameters extends AlgorithmParametersSpi {
@SuppressWarnings("deprecation")
private String parseKDF(DerValue keyDerivationFunc) throws IOException {
String kdfAlgo = null;
if (!pkcs5PBKDF2_OID.equals(keyDerivationFunc.data.getOID())) {
throw new IOException("PBE parameter parsing error: "
@ -318,34 +302,41 @@ abstract class PBES2Parameters extends AlgorithmParametersSpi {
+ "not an ASN.1 OCTET STRING tag");
}
iCount = pBKDF2_params.data.getInteger();
DerValue keyLength = pBKDF2_params.data.getDerValue();
if (keyLength.tag == DerValue.tag_Integer) {
keysize = keyLength.getInteger() * 8; // keysize (in bits)
}
if (pBKDF2_params.tag == DerValue.tag_Sequence) {
DerValue prf = pBKDF2_params.data.getDerValue();
kdfAlgo_OID = prf.data.getOID();
if (hmacWithSHA1_OID.equals(kdfAlgo_OID)) {
kdfAlgo = "HmacSHA1";
} else if (hmacWithSHA224_OID.equals(kdfAlgo_OID)) {
kdfAlgo = "HmacSHA224";
} else if (hmacWithSHA256_OID.equals(kdfAlgo_OID)) {
kdfAlgo = "HmacSHA256";
} else if (hmacWithSHA384_OID.equals(kdfAlgo_OID)) {
kdfAlgo = "HmacSHA384";
} else if (hmacWithSHA512_OID.equals(kdfAlgo_OID)) {
kdfAlgo = "HmacSHA512";
} else {
throw new IOException("PBE parameter parsing error: "
+ "expecting the object identifier for a HmacSHA key "
+ "derivation function");
// keyLength INTEGER (1..MAX) OPTIONAL,
if (pBKDF2_params.data.available() > 0) {
DerValue keyLength = pBKDF2_params.data.getDerValue();
if (keyLength.tag == DerValue.tag_Integer) {
keysize = keyLength.getInteger() * 8; // keysize (in bits)
}
if (prf.data.available() != 0) {
// parameter is 'NULL' for all HmacSHA KDFs
DerValue parameter = prf.data.getDerValue();
if (parameter.tag != DerValue.tag_Null) {
}
// prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1
String kdfAlgo = "HmacSHA1";
if (pBKDF2_params.data.available() > 0) {
if (pBKDF2_params.tag == DerValue.tag_Sequence) {
DerValue prf = pBKDF2_params.data.getDerValue();
kdfAlgo_OID = prf.data.getOID();
if (hmacWithSHA1_OID.equals(kdfAlgo_OID)) {
kdfAlgo = "HmacSHA1";
} else if (hmacWithSHA224_OID.equals(kdfAlgo_OID)) {
kdfAlgo = "HmacSHA224";
} else if (hmacWithSHA256_OID.equals(kdfAlgo_OID)) {
kdfAlgo = "HmacSHA256";
} else if (hmacWithSHA384_OID.equals(kdfAlgo_OID)) {
kdfAlgo = "HmacSHA384";
} else if (hmacWithSHA512_OID.equals(kdfAlgo_OID)) {
kdfAlgo = "HmacSHA512";
} else {
throw new IOException("PBE parameter parsing error: "
+ "not an ASN.1 NULL tag");
+ "expecting the object identifier for a HmacSHA key "
+ "derivation function");
}
if (prf.data.available() != 0) {
// parameter is 'NULL' for all HmacSHA KDFs
DerValue parameter = prf.data.getDerValue();
if (parameter.tag != DerValue.tag_Null) {
throw new IOException("PBE parameter parsing error: "
+ "not an ASN.1 NULL tag");
}
}
}
}
@ -399,8 +390,6 @@ abstract class PBES2Parameters extends AlgorithmParametersSpi {
protected byte[] engineGetEncoded() throws IOException {
DerOutputStream out = new DerOutputStream();
DerOutputStream pBES2Algorithms = new DerOutputStream();
pBES2Algorithms.putOID(pkcs5PBES2_OID);
DerOutputStream pBES2_params = new DerOutputStream();
@ -410,7 +399,10 @@ abstract class PBES2Parameters extends AlgorithmParametersSpi {
DerOutputStream pBKDF2_params = new DerOutputStream();
pBKDF2_params.putOctetString(salt); // choice: 'specified OCTET STRING'
pBKDF2_params.putInteger(iCount);
pBKDF2_params.putInteger(keysize / 8); // derived key length (in octets)
if (keysize > 0) {
pBKDF2_params.putInteger(keysize / 8); // derived key length (in octets)
}
DerOutputStream prf = new DerOutputStream();
// algorithm is id-hmacWithSHA1/SHA224/SHA256/SHA384/SHA512
@ -434,8 +426,7 @@ abstract class PBES2Parameters extends AlgorithmParametersSpi {
}
pBES2_params.write(DerValue.tag_Sequence, encryptionScheme);
pBES2Algorithms.write(DerValue.tag_Sequence, pBES2_params);
out.write(DerValue.tag_Sequence, pBES2Algorithms);
out.write(DerValue.tag_Sequence, pBES2_params);
return out.toByteArray();
}