8000415: Add support for SHA-3

Add SHA-3 support to SUN and OracleUcrypto provider

Reviewed-by: ascarpino, jnimeh
This commit is contained in:
Valerie Peng 2016-05-14 03:44:30 +00:00
parent 6c51be077a
commit b40b6a2e8e
19 changed files with 1460 additions and 641 deletions
jdk
make/mapfiles/libj2ucrypto
src
test
com/oracle/security/ucrypto
sun/security/provider/MessageDigest

@ -1,5 +1,5 @@
#
# Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2012, 2016, 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
@ -30,28 +30,35 @@ SUNWprivate_1.1 {
JNI_OnLoad;
Java_com_oracle_security_ucrypto_UcryptoProvider_loadLibraries;
Java_com_oracle_security_ucrypto_UcryptoProvider_getMechList;
Java_com_oracle_security_ucrypto_NativeDigest_nativeInit;
Java_com_oracle_security_ucrypto_NativeDigestMD_nativeInit;
Java_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate;
Java_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest;
Java_com_oracle_security_ucrypto_NativeDigestMD_nativeClone;
Java_com_oracle_security_ucrypto_NativeDigestMD_nativeFree;
Java_com_oracle_security_ucrypto_NativeDigest_nativeInit;
Java_com_oracle_security_ucrypto_NativeDigest_nativeUpdate;
Java_com_oracle_security_ucrypto_NativeDigest_nativeDigest;
Java_com_oracle_security_ucrypto_NativeDigest_nativeClone;
Java_com_oracle_security_ucrypto_NativeDigest_nativeFree;
Java_com_oracle_security_ucrypto_NativeCipher_nativeInit;
Java_com_oracle_security_ucrypto_NativeCipher_nativeUpdate;
Java_com_oracle_security_ucrypto_NativeCipher_nativeFinal;
Java_com_oracle_security_ucrypto_NativeCipher_nativeInit;
Java_com_oracle_security_ucrypto_NativeCipher_nativeUpdate;
Java_com_oracle_security_ucrypto_NativeCipher_nativeFinal;
Java_com_oracle_security_ucrypto_NativeKey_nativeFree;
Java_com_oracle_security_ucrypto_NativeKey_00024RSAPrivate_nativeInit;
Java_com_oracle_security_ucrypto_NativeKey_00024RSAPrivateCrt_nativeInit;
Java_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeInit;
Java_com_oracle_security_ucrypto_NativeRSASignature_nativeInit;
Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII;
Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI;
Java_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal;
Java_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic;
Java_com_oracle_security_ucrypto_NativeRSASignature_nativeInit;
Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII;
Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI;
Java_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal;
Java_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic;
JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeInit;
JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate;
JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest;
JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeClone;
JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeFree;
JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeInit;
JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate;
JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest;
JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeClone;
JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeFree;
JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeInit;
JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeUpdate;
@ -60,10 +67,10 @@ SUNWprivate_1.1 {
JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPrivate_nativeInit;
JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPrivateCrt_nativeInit;
JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeInit;
JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeInit;
JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII;
JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI;
JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal;
JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeInit;
JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII;
JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI;
JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal;
JavaCritical_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic;
local:

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2016, 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
@ -441,17 +441,89 @@ final class ByteArrayAccess {
(outOfs < 0) || ((out.length - outOfs) < len)) {
throw new ArrayIndexOutOfBoundsException();
}
len += outOfs;
while (outOfs < len) {
long i = in[inOfs++];
out[outOfs++] = (byte)(i >> 56);
out[outOfs++] = (byte)(i >> 48);
out[outOfs++] = (byte)(i >> 40);
out[outOfs++] = (byte)(i >> 32);
out[outOfs++] = (byte)(i >> 24);
out[outOfs++] = (byte)(i >> 16);
out[outOfs++] = (byte)(i >> 8);
out[outOfs++] = (byte)(i );
if (littleEndianUnaligned) {
outOfs += byteArrayOfs;
len += outOfs;
while (outOfs < len) {
unsafe.putLong(out, (long)outOfs, reverseBytes(in[inOfs++]));
outOfs += 8;
}
} else {
len += outOfs;
while (outOfs < len) {
long i = in[inOfs++];
out[outOfs++] = (byte)(i >> 56);
out[outOfs++] = (byte)(i >> 48);
out[outOfs++] = (byte)(i >> 40);
out[outOfs++] = (byte)(i >> 32);
out[outOfs++] = (byte)(i >> 24);
out[outOfs++] = (byte)(i >> 16);
out[outOfs++] = (byte)(i >> 8);
out[outOfs++] = (byte)(i );
}
}
}
/**
* byte[] to long[] conversion, little endian byte order
*/
static void b2lLittle(byte[] in, int inOfs, long[] out, int outOfs, int len) {
if ((inOfs < 0) || ((in.length - inOfs) < len) ||
((outOfs < 0) || (out.length - outOfs) < len/8)) {
throw new ArrayIndexOutOfBoundsException();
}
if (littleEndianUnaligned) {
inOfs += byteArrayOfs;
len += inOfs;
while (inOfs < len) {
out[outOfs++] = unsafe.getLong(in, (long)inOfs);
inOfs += 8;
}
} else {
len += inOfs;
while (inOfs < len) {
out[outOfs++] = ((in[inOfs ] & 0xffL)
| ((in[inOfs + 1] & 0xffL) << 8)
| ((in[inOfs + 2] & 0xffL) << 16)
| ((in[inOfs + 3] & 0xffL) << 24)
| ((in[inOfs + 4] & 0xffL) << 32)
| ((in[inOfs + 5] & 0xffL) << 40)
| ((in[inOfs + 6] & 0xffL) << 48)
| ((in[inOfs + 7] & 0xffL) << 56));
inOfs += 8;
}
}
}
/**
* long[] to byte[] conversion, little endian byte order
*/
static void l2bLittle(long[] in, int inOfs, byte[] out, int outOfs, int len) {
if ((inOfs < 0) || ((in.length - inOfs) < len/8) ||
(outOfs < 0) || ((out.length - outOfs) < len)) {
throw new ArrayIndexOutOfBoundsException();
}
if (littleEndianUnaligned) {
outOfs += byteArrayOfs;
len += outOfs;
while (outOfs < len) {
unsafe.putLong(out, (long)outOfs, in[inOfs++]);
outOfs += 8;
}
} else {
len += outOfs;
while (outOfs < len) {
long i = in[inOfs++];
out[outOfs++] = (byte)(i );
out[outOfs++] = (byte)(i >> 8);
out[outOfs++] = (byte)(i >> 16);
out[outOfs++] = (byte)(i >> 24);
out[outOfs++] = (byte)(i >> 32);
out[outOfs++] = (byte)(i >> 40);
out[outOfs++] = (byte)(i >> 48);
out[outOfs++] = (byte)(i >> 56);
}
}
}
}

@ -0,0 +1,300 @@
/*
* Copyright (c) 2016, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.security.provider;
import static sun.security.provider.ByteArrayAccess.*;
import java.nio.*;
import java.util.*;
import java.security.*;
/**
* This class implements the Secure Hash Algorithm SHA-3 developed by
* the National Institute of Standards and Technology along with the
* National Security Agency as defined in FIPS PUB 202.
*
* <p>It implements java.security.MessageDigestSpi, and can be used
* through Java Cryptography Architecture (JCA), as a pluggable
* MessageDigest implementation.
*
* @since 9
* @author Valerie Peng
*/
abstract class SHA3 extends DigestBase {
private static final int WIDTH = 200; // in bytes, e.g. 1600 bits
private static final int DM = 5; // dimension of lanes
private static final int NR = 24; // number of rounds
// precomputed round constants needed by the step mapping Iota
private static final long[] RC_CONSTANTS = {
0x01L, 0x8082L, 0x800000000000808aL,
0x8000000080008000L, 0x808bL, 0x80000001L,
0x8000000080008081L, 0x8000000000008009L, 0x8aL,
0x88L, 0x80008009L, 0x8000000aL,
0x8000808bL, 0x800000000000008bL, 0x8000000000008089L,
0x8000000000008003L, 0x8000000000008002L, 0x8000000000000080L,
0x800aL, 0x800000008000000aL, 0x8000000080008081L,
0x8000000000008080L, 0x80000001L, 0x8000000080008008L,
};
private byte[] state;
/**
* Creates a new SHA-3 object.
*/
SHA3(String name, int digestLength) {
super(name, digestLength, (WIDTH - (2 * digestLength)));
implReset();
}
/**
* Core compression function. Processes blockSize bytes at a time
* and updates the state of this object.
*/
void implCompress(byte[] b, int ofs) {
for (int i = 0; i < buffer.length; i++) {
state[i] ^= b[ofs++];
}
state = keccak(state);
}
/**
* Return the digest. Subclasses do not need to reset() themselves,
* DigestBase calls implReset() when necessary.
*/
void implDigest(byte[] out, int ofs) {
int numOfPadding =
setPaddingBytes(buffer, (int)(bytesProcessed % buffer.length));
if (numOfPadding < 1) {
throw new ProviderException("Incorrect pad size: " + numOfPadding);
}
for (int i = 0; i < buffer.length; i++) {
state[i] ^= buffer[i];
}
state = keccak(state);
System.arraycopy(state, 0, out, ofs, engineGetDigestLength());
}
/**
* Resets the internal state to start a new hash.
*/
void implReset() {
state = new byte[WIDTH];
}
/**
* Utility function for circular shift the specified long
* value to the left for n bits.
*/
private static long circularShiftLeft(long lane, int n) {
return ((lane << n) | (lane >>> (64 - n)));
}
/**
* Utility function for padding the specified data based on the
* pad10*1 algorithm (section 5.1) and the 2-bit suffix "01" required
* for SHA-3 hash (section 6.1).
*/
private static int setPaddingBytes(byte[] in, int len) {
if (len != in.length) {
// erase leftover values
Arrays.fill(in, len, in.length, (byte)0);
// directly store the padding bytes into the input
// as the specified buffer is allocated w/ size = rateR
in[len] |= (byte) 0x06;
in[in.length - 1] |= (byte) 0x80;
}
return (in.length - len);
}
/**
* Utility function for transforming the specified state from
* the byte array format into array of lanes as defined in
* section 3.1.2.
*/
private static long[][] bytes2Lanes(byte[] s) {
if (s.length != WIDTH) {
throw new ProviderException("Error: incorrect input size " +
s.length);
}
// The conversion traverses along x-axis before y-axis. So, y is the
// first dimension and x is the second dimension.
long[][] s2 = new long[DM][DM];
int sOfs = 0;
for (int y = 0; y < DM; y++, sOfs += 40) {
b2lLittle(s, sOfs, s2[y], 0, 40);
}
return s2;
}
/**
* Utility function for transforming the specified arrays of
* lanes into a byte array as defined in section 3.1.3.
*/
private static byte[] lanes2Bytes(long[][] m) {
byte[] s = new byte[WIDTH];
int sOfs = 0;
// The conversion traverses along x-axis before y-axis. So, y is the
// first dimension and x is the second dimension.
for (int y = 0; y < DM; y++, sOfs += 40) {
l2bLittle(m[y], 0, s, sOfs, 40);
}
return s;
}
/**
* Step mapping Theta as defined in section 3.2.1 .
*/
private static long[][] smTheta(long[][] a) {
long[] c = new long[DM];
for (int i = 0; i < DM; i++) {
c[i] = a[0][i]^a[1][i]^a[2][i]^a[3][i]^a[4][i];
}
long[] d = new long[DM];
for (int i = 0; i < DM; i++) {
long c1 = c[(i + 4) % DM];
// left shift and wrap the leftmost bit into the rightmost bit
long c2 = circularShiftLeft(c[(i + 1) % DM], 1);
d[i] = c1^c2;
}
for (int y = 0; y < DM; y++) {
for (int x = 0; x < DM; x++) {
a[y][x] ^= d[x];
}
}
return a;
}
/**
* Step mapping Rho as defined in section 3.2.2.
*/
private static long[][] smRho(long[][] a) {
long[][] a2 = new long[DM][DM];
a2[0][0] = a[0][0];
int xNext, yNext;
for (int t = 0, x = 1, y = 0; t <= 23; t++, x = xNext, y = yNext) {
int numberOfShift = ((t + 1)*(t + 2)/2) % 64;
a2[y][x] = circularShiftLeft(a[y][x], numberOfShift);
xNext = y;
yNext = (2 * x + 3 * y) % DM;
}
return a2;
}
/**
* Step mapping Pi as defined in section 3.2.3.
*/
private static long[][] smPi(long[][] a) {
long[][] a2 = new long[DM][DM];
for (int y = 0; y < DM; y++) {
for (int x = 0; x < DM; x++) {
a2[y][x] = a[x][(x + 3 * y) % DM];
}
}
return a2;
}
/**
* Step mapping Chi as defined in section 3.2.4.
*/
private static long[][] smChi(long[][] a) {
long[][] a2 = new long[DM][DM];
for (int y = 0; y < DM; y++) {
for (int x = 0; x < DM; x++) {
a2[y][x] = a[y][x] ^
((a[y][(x + 1) % DM] ^ 0xFFFFFFFFFFFFFFFFL) &
a[y][(x + 2) % DM]);
}
}
return a2;
}
/**
* Step mapping Iota as defined in section 3.2.5.
*
* @return the processed state array
* @param state the state array to be processed
*/
private static long[][] smIota(long[][] a, int rndIndex) {
a[0][0] ^= RC_CONSTANTS[rndIndex];
return a;
}
/**
* The function Keccak as defined in section 5.2 with
* rate r = 1600 and capacity c = (digest length x 2).
*/
private static byte[] keccak(byte[] state) {
long[][] lanes = bytes2Lanes(state);
for (int ir = 0; ir < NR; ir++) {
lanes = smIota(smChi(smPi(smRho(smTheta(lanes)))), ir);
}
return lanes2Bytes(lanes);
}
public Object clone() throws CloneNotSupportedException {
SHA3 copy = (SHA3) super.clone();
copy.state = copy.state.clone();
return copy;
}
/**
* SHA3-224 implementation class.
*/
public static final class SHA224 extends SHA3 {
public SHA224() {
super("SHA3-224", 28);
}
}
/**
* SHA3-256 implementation class.
*/
public static final class SHA256 extends SHA3 {
public SHA256() {
super("SHA3-256", 32);
}
}
/**
* SHAs-384 implementation class.
*/
public static final class SHA384 extends SHA3 {
public SHA384() {
super("SHA3-384", 48);
}
}
/**
* SHA3-512 implementation class.
*/
public static final class SHA512 extends SHA3 {
public SHA512() {
super("SHA3-512", 64);
}
}
}

@ -211,6 +211,25 @@ final class SunEntries {
map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.6",
"SHA-512/256");
map.put("MessageDigest.SHA3-224", "sun.security.provider.SHA3$SHA224");
map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.7", "SHA3-224");
map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.7",
"SHA3-224");
map.put("MessageDigest.SHA3-256", "sun.security.provider.SHA3$SHA256");
map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.8", "SHA3-256");
map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.8",
"SHA3-256");
map.put("MessageDigest.SHA3-384", "sun.security.provider.SHA3$SHA384");
map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.9", "SHA3-384");
map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.9",
"SHA3-384");
map.put("MessageDigest.SHA3-512", "sun.security.provider.SHA3$SHA512");
map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.10", "SHA3-512");
map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.10",
"SHA3-512");
/*
* Algorithm Parameter Generator engines
*/

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2016, 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
@ -108,7 +108,7 @@ final class HandshakeHash {
* a hash for the certificate verify message is required.
*/
HandshakeHash(boolean needCertificateVerify) {
clonesNeeded = needCertificateVerify ? 3 : 2;
clonesNeeded = needCertificateVerify ? 4 : 3;
}
void reserve(ByteBuffer input) {

@ -0,0 +1,66 @@
/**
* Copyright (c) 2016, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.security.ucrypto;
/**
* Enum for representing the ucrypto mechanisms.
*
* @since 9
*/
public enum LibMDMech {
MD5(new ServiceDesc[]
{ sd("MessageDigest", "MD5", "com.oracle.security.ucrypto.NativeDigestMD$MD5")
}),
SHA_1(new ServiceDesc[]
{ sd("MessageDigest", "SHA", "com.oracle.security.ucrypto.NativeDigestMD$SHA1",
"SHA-1", "SHA1")
}),
SHA_256(new ServiceDesc[]
{ sd("MessageDigest", "SHA-256", "com.oracle.security.ucrypto.NativeDigestMD$SHA256",
"2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1")
}),
SHA_384(new ServiceDesc[]
{ sd("MessageDigest", "SHA-384", "com.oracle.security.ucrypto.NativeDigestMD$SHA384",
"2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2")
}),
SHA_512(new ServiceDesc[]
{ sd("MessageDigest", "SHA-512", "com.oracle.security.ucrypto.NativeDigestMD$SHA512",
"2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3")
});
ServiceDesc[] serviceDescs;
private static ServiceDesc sd(String type, String algo, String cn, String... aliases) {
return new ServiceDesc(type, algo, cn, aliases);
}
LibMDMech(ServiceDesc[] serviceDescs) {
this.serviceDescs = serviceDescs;
}
public ServiceDesc[] getServiceDescriptions() { return serviceDescs; }
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2016, 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
@ -33,23 +33,67 @@ import java.util.concurrent.ConcurrentSkipListSet;
import java.security.*;
/**
* MessageDigest implementation class. This class currently supports
* MD5, SHA1, SHA256, SHA384, and SHA512
* MessageDigest implementation class using native Ucrypto API.
* This class currently supports: MD5, SHA-2 (224, 256, 384, 512)
* and SHA-3 (224, 256, 384, 512) digests
*
* @since 9
*/
public abstract class NativeDigest extends MessageDigestSpi
implements Cloneable {
abstract class NativeDigest extends MessageDigestSpi {
private static final int MECH_MD5 = 1;
private static final int MECH_SHA1 = 2;
private static final int MECH_SHA256 = 3;
private static final int MECH_SHA224 = 4;
private static final int MECH_SHA384 = 5;
private static final int MECH_SHA512 = 6;
public static final class MD5 extends NativeDigest {
public MD5() {
super(UcryptoMech.CRYPTO_MD5, 16);
}
}
public static final class SHA1 extends NativeDigest {
public SHA1() {
super(UcryptoMech.CRYPTO_SHA1, 20);
}
}
public static final class SHA224 extends NativeDigest {
public SHA224() {
super(UcryptoMech.CRYPTO_SHA224, 28);
}
}
public static final class SHA256 extends NativeDigest {
public SHA256() {
super(UcryptoMech.CRYPTO_SHA256, 32);
}
}
public static final class SHA384 extends NativeDigest {
public SHA384() {
super(UcryptoMech.CRYPTO_SHA384, 48);
}
}
public static final class SHA512 extends NativeDigest {
public SHA512() {
super(UcryptoMech.CRYPTO_SHA512, 64);
}
}
public static final class SHA3_224 extends NativeDigest {
public SHA3_224() {
super(UcryptoMech.CRYPTO_SHA3_224, 28);
}
}
public static final class SHA3_256 extends NativeDigest {
public SHA3_256() {
super(UcryptoMech.CRYPTO_SHA3_256, 32);
}
}
public static final class SHA3_384 extends NativeDigest {
public SHA3_384() {
super(UcryptoMech.CRYPTO_SHA3_384, 48);
}
}
public static final class SHA3_512 extends NativeDigest {
public SHA3_512() {
super(UcryptoMech.CRYPTO_SHA3_512, 64);
}
}
private final int digestLen;
private final int mech;
private final UcryptoMech mech;
// field for ensuring native memory is freed
private DigestContextRef pCtxt = null;
@ -64,10 +108,9 @@ public abstract class NativeDigest extends MessageDigestSpi
// referents are GC'ed so we can do post-mortem processing
private static Set<DigestContextRef> refList =
new ConcurrentSkipListSet<DigestContextRef>();
// Collections.synchronizedSortedSet(new TreeSet<DigestContextRef>());
private final long id;
private final int mech;
private final UcryptoMech mech;
private static void drainRefQueueBounded() {
while (true) {
@ -77,7 +120,7 @@ public abstract class NativeDigest extends MessageDigestSpi
}
}
DigestContextRef(NativeDigest nc, long id, int mech) {
DigestContextRef(NativeDigest nc, long id, UcryptoMech mech) {
super(nc, refQueue);
this.id = id;
this.mech = mech;
@ -98,18 +141,22 @@ public abstract class NativeDigest extends MessageDigestSpi
refList.remove(this);
try {
if (needFree) {
UcryptoProvider.debug("Resource: free Digest Ctxt " + this.id);
NativeDigest.nativeFree(mech, id);
} else UcryptoProvider.debug("Resource: stop tracking Digest Ctxt " + this.id);
UcryptoProvider.debug("Resource: free Digest Ctxt " +
this.id);
NativeDigest.nativeFree(mech.value(), id);
} else {
UcryptoProvider.debug("Resource: discard Digest Ctxt " +
this.id);
}
} finally {
this.clear();
}
}
}
NativeDigest(int mech, int digestLen) {
this.digestLen = digestLen;
NativeDigest(UcryptoMech mech, int digestLen) {
this.mech = mech;
this.digestLen = digestLen;
}
// see JCA spec
@ -153,10 +200,10 @@ public abstract class NativeDigest extends MessageDigestSpi
}
if (pCtxt == null) {
pCtxt = new DigestContextRef(this, nativeInit(mech), mech);
pCtxt = new DigestContextRef(this, nativeInit(mech.value()), mech);
}
try {
int status = nativeDigest(mech, pCtxt.id, out, ofs, digestLen);
int status = nativeDigest(mech.value(), pCtxt.id, out, ofs, digestLen);
if (status != 0) {
throw new DigestException("Internal error: " + status);
}
@ -183,64 +230,24 @@ public abstract class NativeDigest extends MessageDigestSpi
+ len + ". in.length: " + in.length);
}
if (pCtxt == null) {
pCtxt = new DigestContextRef(this, nativeInit(mech), mech);
pCtxt = new DigestContextRef(this, nativeInit(mech.value()), mech);
}
nativeUpdate(mech, pCtxt.id, in, ofs, len);
nativeUpdate(mech.value(), pCtxt.id, in, ofs, len);
}
/**
* Clone this digest.
*/
public synchronized Object clone() throws CloneNotSupportedException {
NativeDigest copy = (NativeDigest) super.clone();
// re-work the fields that cannot be copied over
if (pCtxt != null) {
copy.pCtxt = new DigestContextRef(this, nativeClone(mech, pCtxt.id), mech);
}
return copy;
throw new CloneNotSupportedException("Clone is not supported");
}
// return pointer to the context
protected static native long nativeInit(int mech);
protected static final native long nativeInit(int mech);
// return status code; always 0
protected static native int nativeUpdate(int mech, long pCtxt, byte[] in, int ofs, int inLen);
protected static final native int nativeUpdate(int mech, long pCtxt, byte[] in, int ofs, int inLen);
// return status code; always 0
protected static native int nativeDigest(int mech, long pCtxt, byte[] out, int ofs, int digestLen);
// return pointer to the duplicated context
protected static native long nativeClone(int mech, long pCtxt);
protected static final native int nativeDigest(int mech, long pCtxt, byte[] out, int ofs, int digestLen);
// free the specified context
private native static void nativeFree(int mech, long id);
public static final class MD5 extends NativeDigest {
public MD5() {
super(MECH_MD5, 16);
}
}
public static final class SHA1 extends NativeDigest {
public SHA1() {
super(MECH_SHA1, 20);
}
}
public static final class SHA256 extends NativeDigest {
public SHA256() {
super(MECH_SHA256, 32);
}
}
public static final class SHA384 extends NativeDigest {
public SHA384() {
super(MECH_SHA384, 48);
}
}
public static final class SHA512 extends NativeDigest {
public SHA512() {
super(MECH_SHA512, 64);
}
}
private static final native void nativeFree(int mech, long id);
}

@ -0,0 +1,246 @@
/*
* Copyright (c) 2016, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.security.ucrypto;
import java.lang.ref.*;
import java.io.ByteArrayOutputStream;
import java.util.*;
import java.util.concurrent.ConcurrentSkipListSet;
import java.security.*;
/**
* MessageDigest implementation class for libMD API. This class currently supports
* MD5, SHA1, SHA256, SHA384, and SHA512
*
* @since 9
*/
public abstract class NativeDigestMD extends MessageDigestSpi
implements Cloneable {
private static final int MECH_MD5 = 1;
private static final int MECH_SHA1 = 2;
private static final int MECH_SHA256 = 3;
private static final int MECH_SHA224 = 4;
private static final int MECH_SHA384 = 5;
private static final int MECH_SHA512 = 6;
private final int digestLen;
private final int mech;
// field for ensuring native memory is freed
private DigestContextRef pCtxt = null;
private static class DigestContextRef extends PhantomReference<NativeDigestMD>
implements Comparable<DigestContextRef> {
private static ReferenceQueue<NativeDigestMD> refQueue =
new ReferenceQueue<NativeDigestMD>();
// Needed to keep these references from being GC'ed until when their
// referents are GC'ed so we can do post-mortem processing
private static Set<DigestContextRef> refList =
new ConcurrentSkipListSet<DigestContextRef>();
// Collections.synchronizedSortedSet(new TreeSet<DigestContextRef>());
private final long id;
private final int mech;
private static void drainRefQueueBounded() {
while (true) {
DigestContextRef next = (DigestContextRef) refQueue.poll();
if (next == null) break;
next.dispose(true);
}
}
DigestContextRef(NativeDigestMD nc, long id, int mech) {
super(nc, refQueue);
this.id = id;
this.mech = mech;
refList.add(this);
UcryptoProvider.debug("Resource: track Digest Ctxt " + this.id);
drainRefQueueBounded();
}
public int compareTo(DigestContextRef other) {
if (this.id == other.id) {
return 0;
} else {
return (this.id < other.id) ? -1 : 1;
}
}
void dispose(boolean needFree) {
refList.remove(this);
try {
if (needFree) {
UcryptoProvider.debug("Resource: free Digest Ctxt " + this.id);
NativeDigestMD.nativeFree(mech, id);
} else UcryptoProvider.debug("Resource: stop tracking Digest Ctxt " + this.id);
} finally {
this.clear();
}
}
}
NativeDigestMD(int mech, int digestLen) {
this.digestLen = digestLen;
this.mech = mech;
}
// see JCA spec
protected int engineGetDigestLength() {
return digestLen;
}
// see JCA spec
protected synchronized void engineReset() {
if (pCtxt != null) {
pCtxt.dispose(true);
pCtxt = null;
}
}
// see JCA spec
protected synchronized byte[] engineDigest() {
byte[] digest = new byte[digestLen];
try {
int len = engineDigest(digest, 0, digestLen);
if (len != digestLen) {
throw new UcryptoException("Digest length mismatch." +
" Len: " + len + ". digestLen: " + digestLen);
}
return digest;
} catch (DigestException de) {
throw new UcryptoException("Internal error", de);
}
}
// see JCA spec
protected synchronized int engineDigest(byte[] out, int ofs, int len)
throws DigestException {
if (len < digestLen) {
throw new DigestException("Output buffer must be at least " +
digestLen + " bytes long. Got: " + len);
}
if ((ofs < 0) || (len < 0) || (ofs > out.length - len)) {
throw new DigestException("Buffer too short to store digest. " +
"ofs: " + ofs + ". len: " + len + ". out.length: " + out.length);
}
if (pCtxt == null) {
pCtxt = new DigestContextRef(this, nativeInit(mech), mech);
}
try {
int status = nativeDigest(mech, pCtxt.id, out, ofs, digestLen);
if (status != 0) {
throw new DigestException("Internal error: " + status);
}
} finally {
pCtxt.dispose(false);
pCtxt = null;
}
return digestLen;
}
// see JCA spec
protected synchronized void engineUpdate(byte in) {
byte[] temp = { in };
engineUpdate(temp, 0, 1);
}
// see JCA spec
protected synchronized void engineUpdate(byte[] in, int ofs, int len) {
if (len == 0) {
return;
}
if ((ofs < 0) || (len < 0) || (ofs > in.length - len)) {
throw new ArrayIndexOutOfBoundsException("ofs: " + ofs + ". len: "
+ len + ". in.length: " + in.length);
}
if (pCtxt == null) {
pCtxt = new DigestContextRef(this, nativeInit(mech), mech);
}
nativeUpdate(mech, pCtxt.id, in, ofs, len);
}
/**
* Clone this digest.
*/
public synchronized Object clone() throws CloneNotSupportedException {
NativeDigestMD copy = (NativeDigestMD) super.clone();
// re-work the fields that cannot be copied over
if (pCtxt != null) {
copy.pCtxt = new DigestContextRef(this, nativeClone(mech, pCtxt.id), mech);
}
return copy;
}
// return pointer to the context
protected static final native long nativeInit(int mech);
// return status code; always 0
protected static final native int nativeUpdate(int mech, long pCtxt, byte[] in, int ofs, int inLen);
// return status code; always 0
protected static final native int nativeDigest(int mech, long pCtxt, byte[] out, int ofs, int digestLen);
// return pointer to the duplicated context
protected static final native long nativeClone(int mech, long pCtxt);
// free the specified context
private static final native void nativeFree(int mech, long id);
public static final class MD5 extends NativeDigestMD {
public MD5() {
super(MECH_MD5, 16);
}
}
public static final class SHA1 extends NativeDigestMD {
public SHA1() {
super(MECH_SHA1, 20);
}
}
public static final class SHA256 extends NativeDigestMD {
public SHA256() {
super(MECH_SHA256, 32);
}
}
public static final class SHA384 extends NativeDigestMD {
public SHA384() {
super(MECH_SHA384, 48);
}
}
public static final class SHA512 extends NativeDigestMD {
public SHA512() {
super(MECH_SHA512, 64);
}
}
}

@ -1,5 +1,5 @@
/**
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2016, 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
@ -25,8 +25,6 @@
package com.oracle.security.ucrypto;
import java.util.HashMap;
/**
* Enum for representing the ucrypto mechanisms.
*
@ -35,78 +33,126 @@ import java.util.HashMap;
// Check /usr/include/libsoftcrypto.h for updates
public enum UcryptoMech {
CRYPTO_AES_ECB(1, new ServiceDesc[]
CRYPTO_AES_ECB(new ServiceDesc[]
{ sd("Cipher", "AES/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding"),
sd("Cipher", "AES/ECB/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesEcbPKCS5",
"AES"),
sd("Cipher", "AES_128/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes128EcbNoPadding",
sd("Cipher", "AES_128/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding",
"2.16.840.1.101.3.4.1.1", "OID.2.16.840.1.101.3.4.1.1"),
sd("Cipher", "AES_192/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes192EcbNoPadding",
sd("Cipher", "AES_192/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding",
"2.16.840.1.101.3.4.1.21", "OID.2.16.840.1.101.3.4.1.21"),
sd("Cipher", "AES_256/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes256EcbNoPadding",
sd("Cipher", "AES_256/ECB/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding",
"2.16.840.1.101.3.4.1.41", "OID.2.16.840.1.101.3.4.1.41")
}),
CRYPTO_AES_CBC(2, new ServiceDesc[]
CRYPTO_AES_CBC(new ServiceDesc[]
{ sd("Cipher", "AES/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding"),
sd("Cipher", "AES/CBC/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesCbcPKCS5"),
sd("Cipher", "AES_128/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes128CbcNoPadding",
sd("Cipher", "AES_128/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding",
"2.16.840.1.101.3.4.1.2", "OID.2.16.840.1.101.3.4.1.2"),
sd("Cipher", "AES_192/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes192CbcNoPadding",
sd("Cipher", "AES_192/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding",
"2.16.840.1.101.3.4.1.22", "OID.2.16.840.1.101.3.4.1.22"),
sd("Cipher", "AES_256/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$Aes256CbcNoPadding",
sd("Cipher", "AES_256/CBC/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding",
"2.16.840.1.101.3.4.1.42", "OID.2.16.840.1.101.3.4.1.42")
}),
CRYPTO_AES_CBC_PAD(3, null), // No support from Solaris yet
CRYPTO_AES_CTR(4, new ServiceDesc[]
// CRYPTO_AES_CBC_PAD(null), // Support added since S11.1; however we still use CRYPTO_AES_CBC due to known bug
CRYPTO_AES_CTR(new ServiceDesc[]
{ sd("Cipher", "AES/CTR/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCtrNoPadding") }),
CRYPTO_AES_CCM(5, null), // Cannot support due to lack of Java API which corresponds to CK_AES_CCM_PARAMS
CRYPTO_AES_GCM(6, new ServiceDesc[]
// CRYPTO_AES_CCM(null), // Need Java API for CK_AES_CCM_PARAMS
CRYPTO_AES_GCM(new ServiceDesc[]
{ sd("Cipher", "AES/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding"),
sd("Cipher", "AES_128/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$Aes128GcmNoPadding",
sd("Cipher", "AES_128/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding",
"2.16.840.1.101.3.4.1.6", "OID.2.16.840.1.101.3.4.1.6"),
sd("Cipher", "AES_192/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$Aes192GcmNoPadding",
sd("Cipher", "AES_192/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding",
"2.16.840.1.101.3.4.1.26", "OID.2.16.840.1.101.3.4.1.26"),
sd("Cipher", "AES_256/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$Aes256GcmNoPadding",
sd("Cipher", "AES_256/GCM/NoPadding", "com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding",
"2.16.840.1.101.3.4.1.46", "OID.2.16.840.1.101.3.4.1.46")
}),
CRYPTO_AES_GMAC(7, null), // No support from Solaris yet
CRYPTO_AES_CFB128(8, new ServiceDesc[]
// CRYPTO_AES_GMAC(null), // No support from Solaris
CRYPTO_AES_CFB128(new ServiceDesc[]
{ sd("Cipher", "AES/CFB128/NoPadding", "com.oracle.security.ucrypto.NativeCipher$AesCfb128NoPadding"),
sd("Cipher", "AES/CFB128/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesCfb128PKCS5") }),
CRYPTO_RSA_PKCS(31, new ServiceDesc[]
sd("Cipher", "AES/CFB128/PKCS5Padding", "com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesCfb128PKCS5")
}),
CRYPTO_RSA_PKCS(new ServiceDesc[]
{ sd("Cipher", "RSA/ECB/PKCS1Padding", "com.oracle.security.ucrypto.NativeRSACipher$PKCS1Padding",
"RSA") }),
CRYPTO_RSA_X_509(32, new ServiceDesc[]
"RSA")
}),
CRYPTO_RSA_X_509(new ServiceDesc[]
{ sd("Cipher", "RSA/ECB/NoPadding", "com.oracle.security.ucrypto.NativeRSACipher$NoPadding") }),
CRYPTO_MD5_RSA_PKCS(33, new ServiceDesc[]
CRYPTO_MD5_RSA_PKCS(new ServiceDesc[]
{ sd("Signature", "MD5withRSA", "com.oracle.security.ucrypto.NativeRSASignature$MD5",
"1.2.840.113549.1.1.4", "OID.1.2.840.113549.1.1.4") }),
CRYPTO_SHA1_RSA_PKCS(34, new ServiceDesc[]
"1.2.840.113549.1.1.4", "OID.1.2.840.113549.1.1.4")
}),
CRYPTO_SHA1_RSA_PKCS(new ServiceDesc[]
{ sd("Signature", "SHA1withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA1",
"1.2.840.113549.1.1.5", "OID.1.2.840.113549.1.1.5",
"1.3.14.3.2.29") }),
CRYPTO_SHA256_RSA_PKCS(35, new ServiceDesc[]
"1.3.14.3.2.29")
}),
CRYPTO_SHA256_RSA_PKCS(new ServiceDesc[]
{ sd("Signature", "SHA256withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA256",
"1.2.840.113549.1.1.11", "OID.1.2.840.113549.1.1.11") }),
CRYPTO_SHA384_RSA_PKCS(36, new ServiceDesc[]
"1.2.840.113549.1.1.11", "OID.1.2.840.113549.1.1.11")
}),
CRYPTO_SHA384_RSA_PKCS(new ServiceDesc[]
{ sd("Signature", "SHA384withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA384",
"1.2.840.113549.1.1.12", "OID.1.2.840.113549.1.1.12") }),
CRYPTO_SHA512_RSA_PKCS(37, new ServiceDesc[]
"1.2.840.113549.1.1.12", "OID.1.2.840.113549.1.1.12")
}),
CRYPTO_SHA512_RSA_PKCS(new ServiceDesc[]
{ sd("Signature", "SHA512withRSA", "com.oracle.security.ucrypto.NativeRSASignature$SHA512",
"1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13") });
"1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13")
}),
private final int mech;
CRYPTO_MD5(new ServiceDesc[]
{ sd("MessageDigest", "MD5", "com.oracle.security.ucrypto.NativeDigest$MD5") }),
CRYPTO_SHA1(new ServiceDesc[]
{ sd("MessageDigest", "SHA", "com.oracle.security.ucrypto.NativeDigest$SHA1", "SHA-1", "SHA1") }),
CRYPTO_SHA224(new ServiceDesc[]
{ sd("MessageDigest", "SHA-224", "com.oracle.security.ucrypto.NativeDigest$SHA224",
"2.16.840.1.101.3.4.2.4", "OID.2.16.840.1.101.3.4.2.4")
}),
CRYPTO_SHA256(new ServiceDesc[]
{ sd("MessageDigest", "SHA-256", "com.oracle.security.ucrypto.NativeDigest$SHA256",
"2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1")
}),
CRYPTO_SHA384(new ServiceDesc[]
{ sd("MessageDigest", "SHA-384", "com.oracle.security.ucrypto.NativeDigest$SHA384",
"2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2")
}),
CRYPTO_SHA512(new ServiceDesc[]
{ sd("MessageDigest", "SHA-512", "com.oracle.security.ucrypto.NativeDigest$SHA512",
"2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3")
}),
CRYPTO_SHA3_224(new ServiceDesc[]
{ sd("MessageDigest", "SHA3-224", "com.oracle.security.ucrypto.NativeDigest$SHA3_224",
"2.16.840.1.101.3.4.2.7", "OID.2.16.840.1.101.3.4.2.7")
}),
CRYPTO_SHA3_256(new ServiceDesc[]
{ sd("MessageDigest", "SHA3-256", "com.oracle.security.ucrypto.NativeDigest$SHA3_256",
"2.16.840.1.101.3.4.2.8", "OID.2.16.840.1.101.3.4.2.8")
}),
CRYPTO_SHA3_384(new ServiceDesc[]
{ sd("MessageDigest", "SHA3-384", "com.oracle.security.ucrypto.NativeDigest$SHA3_384",
"2.16.840.1.101.3.4.2.9", "OID.2.16.840.1.101.3.4.2.9")
}),
CRYPTO_SHA3_512(new ServiceDesc[]
{ sd("MessageDigest", "SHA3-512", "com.oracle.security.ucrypto.NativeDigest$SHA3_512",
"2.16.840.1.101.3.4.2.10", "OID.2.16.840.1.101.3.4.2.10")
});
private int mech = 0;
private final ServiceDesc[] serviceDescs;
private static ServiceDesc sd(String type, String algo, String cn, String... aliases) {
return new ServiceDesc(type, algo, cn, aliases);
}
UcryptoMech(int mech, ServiceDesc[] serviceDescs) {
this.mech = mech;
UcryptoMech(ServiceDesc[] serviceDescs) {
this.serviceDescs = serviceDescs;
}
public void setValue(int nativeMechValue) {
this.mech = nativeMechValue;
}
public int value() { return mech; }
public ServiceDesc[] getServiceDescriptions() { return serviceDescs; }
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2016, 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
@ -27,6 +27,7 @@ package com.oracle.security.ucrypto;
import java.io.IOException;
import java.io.File;
import java.lang.reflect.Constructor;
import java.util.*;
import java.security.*;
@ -74,48 +75,52 @@ public final class UcryptoProvider extends Provider {
if (provProp != null) {
boolean[] result = loadLibraries();
if (result.length == 2) {
if (result[0]) { // successfully loaded libmd
provProp.put("MessageDigest.MD5",
sd("MessageDigest", "MD5",
"com.oracle.security.ucrypto.NativeDigest$MD5"));
provProp.put("MessageDigest.SHA",
sd("MessageDigest", "SHA",
"com.oracle.security.ucrypto.NativeDigest$SHA1",
"SHA-1", "SHA1"));
provProp.put("MessageDigest.SHA-256",
sd("MessageDigest", "SHA-256",
"com.oracle.security.ucrypto.NativeDigest$SHA256",
"2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1"));
provProp.put("MessageDigest.SHA-384",
sd("MessageDigest", "SHA-384",
"com.oracle.security.ucrypto.NativeDigest$SHA384",
"2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2"));
provProp.put("MessageDigest.SHA-512",
sd("MessageDigest", "SHA-512",
"com.oracle.security.ucrypto.NativeDigest$SHA512",
"2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3"));
};
if (result[1]) { // successfully loaded libsoftcrypto
// true when libsoftcrypto or libucrypto(S12) has been successfully loaded
if (result[1]) {
String supportedMechs = getMechList();
debug("Prov: supported mechs = " + supportedMechs);
for (UcryptoMech m : UcryptoMech.values()) {
if (supportedMechs.indexOf(m.name() + ",") != -1) {
StringTokenizer st = new StringTokenizer(supportedMechs, ":,;");
// format: numOfSupportedMechs:[mechName,mechValue;]+
// skip the first one which is numberOfSupportedMechs
st.nextToken();
while (st.hasMoreTokens()) {
String mechName = st.nextToken();
int nativeMechVal = Integer.parseInt(st.nextToken());
try {
UcryptoMech m = Enum.valueOf(UcryptoMech.class, mechName);
m.setValue(nativeMechVal);
ServiceDesc[] services = m.getServiceDescriptions();
// skip unsupported UcryptoMech
if (services == null || services.length == 0) continue;
// defined in UcryptoMech as unsupported
if (services == null || services.length == 0) {
debug("Skip Unsupported Algorithm: " + mechName);
continue;
}
for (int p = 0; p < services.length; p++) {
ServiceDesc entry = services[p];
provProp.put(entry.getType() + "." + entry.getAlgorithm(),
entry);
}
} catch (IllegalArgumentException iae) {
// not defined in UcryptoMech
debug("Skip Unrecognized Algorithm: " + mechName);
}
}
// NOTE: GCM support is only available since jdk 7
provProp.put("AlgorithmParameters.GCM",
sd("AlgorithmParameters", "GCM", "com.oracle.security.ucrypto.GCMParameters"));
sd("AlgorithmParameters", "GCM",
"com.oracle.security.ucrypto.GCMParameters"));
}
// true when libmd is needed and has been successfully loaded
if (result[0]) {
for (LibMDMech m : LibMDMech.values()) {
ServiceDesc[] services = m.getServiceDescriptions();
for (ServiceDesc entry : services) {
String sKey = entry.getType() + "." + entry.getAlgorithm();
// only register if none has been registered
provProp.putIfAbsent(sKey, entry);
}
}
};
} else {
debug("Prov: unexpected ucrypto library loading error, got " + result.length);
}
@ -138,6 +143,7 @@ public final class UcryptoProvider extends Provider {
sd.getAliases(), null);
}
@SuppressWarnings("deprecation")
@Override
public Object newInstance(Object ctrParamObj)
throws NoSuchAlgorithmException {
@ -152,53 +158,19 @@ public final class UcryptoProvider extends Provider {
int keySize = -1;
if (algo.charAt(3) == '_') {
keySize = Integer.parseInt(algo.substring(4, 7))/8;
algo = algo.substring(0, 3) + algo.substring(7);
}
if (algo.equals("AES/ECB/NoPadding")) {
return new NativeCipher.AesEcbNoPadding(keySize);
} else if (algo.equals("AES/ECB/PKCS5Padding")) {
return new NativeCipherWithJavaPadding.AesEcbPKCS5();
} else if (algo.equals("AES/CBC/NoPadding")) {
return new NativeCipher.AesCbcNoPadding(keySize);
} else if (algo.equals("AES/CBC/PKCS5Padding")) {
return new NativeCipherWithJavaPadding.AesCbcPKCS5();
} else if (algo.equals("AES/CTR/NoPadding")) {
return new NativeCipher.AesCtrNoPadding();
} else if (algo.equals("AES/GCM/NoPadding")) {
return new NativeGCMCipher.AesGcmNoPadding(keySize);
} else if (algo.equals("AES/CFB128/NoPadding")) {
return new NativeCipher.AesCfb128NoPadding();
} else if (algo.equals("AES/CFB128/PKCS5Padding")) {
return new NativeCipherWithJavaPadding.AesCfb128PKCS5();
} else if (algo.equals("RSA/ECB/NoPadding")) {
return new NativeRSACipher.NoPadding();
} else if (algo.equals("RSA/ECB/PKCS1Padding")) {
return new NativeRSACipher.PKCS1Padding();
}
} else if (type.equals("Signature")) {
if (algo.equals("SHA1withRSA")) {
return new NativeRSASignature.SHA1();
} else if (algo.equals("SHA256withRSA")) {
return new NativeRSASignature.SHA256();
} else if (algo.equals("SHA384withRSA")) {
return new NativeRSASignature.SHA384();
} else if (algo.equals("SHA512withRSA")) {
return new NativeRSASignature.SHA512();
} else if (algo.equals("MD5withRSA")) {
return new NativeRSASignature.MD5();
}
} else if (type.equals("MessageDigest")) {
if (algo.equals("SHA")) {
return new NativeDigest.SHA1();
} else if (algo.equals("SHA-256")) {
return new NativeDigest.SHA256();
} else if (algo.equals("SHA-384")) {
return new NativeDigest.SHA384();
} else if (algo.equals("SHA-512")) {
return new NativeDigest.SHA512();
} else if (algo.equals("MD5")) {
return new NativeDigest.MD5();
String implClass = getClassName();
Class<?> clz = Class.forName(implClass);
if (keySize != -1) {
Constructor<?> ctr = clz.getConstructor(int.class);
return ctr.newInstance(keySize);
} else {
return clz.newInstance();
}
} else if (type.equals("Signature") || type.equals("MessageDigest")) {
String implClass = getClassName();
Class<?> clz = Class.forName(implClass);
return clz.newInstance();
} else if (type.equals("AlgorithmParameters")) {
if (algo.equals("GCM")) {
return new GCMParameters();

@ -1,183 +0,0 @@
/*
* Copyright (c) 2014, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#ifndef _LIBSOFTCRYPTO_H
#define _LIBSOFTCRYPTO_H
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <strings.h>
typedef enum ucrypto_mech {
CRYPTO_AES_ECB = 1,
CRYPTO_AES_CBC,
CRYPTO_AES_CBC_PAD,
CRYPTO_AES_CTR,
CRYPTO_AES_CCM,
CRYPTO_AES_GCM,
CRYPTO_AES_GMAC,
CRYPTO_AES_CFB128,
CRYPTO_RSA_PKCS = 31,
CRYPTO_RSA_X_509,
CRYPTO_MD5_RSA_PKCS,
CRYPTO_SHA1_RSA_PKCS,
CRYPTO_SHA256_RSA_PKCS,
CRYPTO_SHA384_RSA_PKCS,
CRYPTO_SHA512_RSA_PKCS
} ucrypto_mech_t;
typedef struct crypto_ctx {
void *cc_provider;
uint_t cc_session;
void *cc_provider_private; /* owned by provider */
void *cc_framework_private; /* owned by framework */
uint32_t cc_flags; /* flags */
void *cc_opstate; /* state */
} crypto_ctx_t;
extern int ucrypto_encrypt_init(crypto_ctx_t *context,
ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len,
void *iv, size_t iv_len);
extern int ucrypto_encrypt_update(crypto_ctx_t *context, uchar_t *in,
size_t in_len, uchar_t *out, size_t *out_len);
extern int ucrypto_encrypt_final(crypto_ctx_t *context, uchar_t *out,
size_t *out_len);
/* Encrypt atomic */
extern int ucrypto_encrypt(ucrypto_mech_t mech_type, uchar_t *key_str,
size_t key_len, void *iv, size_t iv_len, uchar_t *in,
size_t in_len, uchar_t *out, size_t *out_len);
/* Decrypt multi-part */
extern int ucrypto_decrypt_init(crypto_ctx_t *context,
ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len,
void *iv, size_t iv_len);
extern int ucrypto_decrypt_update(crypto_ctx_t *context, uchar_t *in,
size_t in_len, uchar_t *out, size_t *out_len);
extern int ucrypto_decrypt_final(crypto_ctx_t *context, uchar_t *out,
size_t *out_len);
/* Decrypt atomic */
extern int ucrypto_decrypt(ucrypto_mech_t mech_type, uchar_t *key_str,
size_t key_len, void *iv, size_t iv_len, uchar_t *in,
size_t in_len, uchar_t *out, size_t *out_len);
/* Sign multi-part */
extern int ucrypto_sign_init(crypto_ctx_t *context, ucrypto_mech_t mech_type,
uchar_t *key_str, size_t key_len, void *iv, size_t iv_len);
extern int ucrypto_sign_update(crypto_ctx_t *context,
uchar_t *data_str, size_t data_len);
extern int ucrypto_sign_final(crypto_ctx_t *context,
uchar_t *sig_str, size_t *sig_len);
/* Sign atomic */
extern int ucrypto_sign(ucrypto_mech_t mech_type,
uchar_t *key_str, size_t key_len, void *iv, size_t iv_len,
uchar_t *data_str, size_t data_len, uchar_t *sig_str, size_t *sig_len);
/* Verify multi-part */
extern int ucrypto_verify_init(crypto_ctx_t *context, ucrypto_mech_t mech_type,
uchar_t *key_str, size_t key_len, void *iv, size_t iv_len);
extern int ucrypto_verify_update(crypto_ctx_t *context,
uchar_t *data_str, size_t data_len);
extern int ucrypto_verify_final(crypto_ctx_t *context,
uchar_t *sig_str, size_t *sig_len);
/* Verify atomic */
extern int ucrypto_verify(ucrypto_mech_t mech_type,
uchar_t *key_str, size_t key_len, void *iv, size_t iv_len,
uchar_t *data_str, size_t data_len, uchar_t *sig, size_t *sig_len);
extern int ucrypto_get_mechlist(char *str);
extern const char *ucrypto_id2mech(ucrypto_mech_t mech_type);
extern ucrypto_mech_t ucrypto_mech2id(const char *str);
extern int ucrypto_version();
typedef struct CK_AES_CTR_PARAMS {
ulong_t ulCounterBits;
uint8_t cb[16];
} CK_AES_CTR_PARAMS;
typedef struct CK_AES_GCM_PARAMS {
uchar_t *pIv;
ulong_t ulIvLen;
ulong_t ulIvBits;
uchar_t *pAAD;
ulong_t ulAADLen;
ulong_t ulTagBits;
} CK_AES_GCM_PARAMS;
typedef struct crypto_object_attribute {
uint64_t oa_type; /* attribute type */
caddr_t oa_value; /* attribute value */
ssize_t oa_value_len; /* length of attribute value */
} crypto_object_attribute_t;
/* Attribute types to use for passing a RSA public key or a private key. */
#define SUN_CKA_MODULUS 0x00000120
#define SUN_CKA_MODULUS_BITS 0x00000121
#define SUN_CKA_PUBLIC_EXPONENT 0x00000122
#define SUN_CKA_PRIVATE_EXPONENT 0x00000123
#define SUN_CKA_PRIME_1 0x00000124
#define SUN_CKA_PRIME_2 0x00000125
#define SUN_CKA_EXPONENT_1 0x00000126
#define SUN_CKA_EXPONENT_2 0x00000127
#define SUN_CKA_COEFFICIENT 0x00000128
#define SUN_CKA_PRIME 0x00000130
#define SUN_CKA_SUBPRIME 0x00000131
#define SUN_CKA_BASE 0x00000132
#define CKK_EC 0x00000003
#define CKK_GENERIC_SECRET 0x00000010
#define CKK_RC4 0x00000012
#define CKK_AES 0x0000001F
#define CKK_DES 0x00000013
#define CKK_DES2 0x00000014
#define CKK_DES3 0x00000015
#define CKO_PUBLIC_KEY 0x00000002
#define CKO_PRIVATE_KEY 0x00000003
#define CKA_CLASS 0x00000000
#define CKA_VALUE 0x00000011
#define CKA_KEY_TYPE 0x00000100
#define CKA_VALUE_LEN 0x00000161
#define CKA_EC_PARAMS 0x00000180
#define CKA_EC_POINT 0x00000181
#endif /* _LIBSOFTCRYPTO_H */

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2016, 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
@ -32,6 +32,22 @@
#include "nativeCrypto.h"
#include "nativeFunc.h"
/*
* Dumps out byte array in hex with and name and length info
*/
void printError(char* header, int mech, int rv) {
if (mech != -1) {
printf("%s, mech = %d, rv = 0x%0x\n", header, mech, rv);
} else {
printf("%s, rv = 0x%0x\n", header, rv);
}
if (*ftab->ucryptoStrerror != NULL) {
char * reason = (*ftab->ucryptoStrerror)(rv);
printf("\tcause = %s\n", reason);
free(reason);
}
}
/*
* Dumps out byte array in hex with and name and length info
*/
@ -60,6 +76,16 @@ void throwOutOfMemoryError(JNIEnv *env, const char *msg)
(*env)->DeleteLocalRef(env, jExClass);
}
/*
* De-allocates all memory associated with crypto_ctx_t
*/
void freeContext(crypto_ctx_t *context) {
if (ftab->ucryptoFreeContext != NULL) {
(*ftab->ucryptoFreeContext)(context);
}
free(context);
}
JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) {
return JNI_VERSION_1_4;
}
@ -203,10 +229,10 @@ CipherInit(crypto_ctx_t *context, int encrypt, ucrypto_mech_t mech,
}
if (encrypt) {
rv = (*ftab->ucryptoEncryptInit)(context, mech, jKey, (size_t)jKeyLen, iv, ivLen);
if (rv != 0 && DEBUG) printf("ucryptoEncryptInit: ret = 0x%x\n", rv);
if (rv != 0 && DEBUG) printError("ucryptoEncryptInit", mech, rv);
} else {
rv =(*ftab->ucryptoDecryptInit)(context, mech, jKey, (size_t)jKeyLen, iv, ivLen);
if (rv != 0 && DEBUG) printf("ucryptoDecryptInit: ret = 0x%x\n", rv);
if (rv != 0 && DEBUG) printError("ucryptoDecryptInit", mech, rv);
}
if (iv != jIv) {
@ -234,15 +260,15 @@ CipherUpdate(crypto_ctx_t *context, int encrypt, unsigned char *bufIn, int inOfs
}
if (encrypt) {
rv = (*ftab->ucryptoEncryptUpdate)(context, (unsigned char*)(bufIn+inOfs), (size_t)inLen, (unsigned char*)(bufOut+outOfs), &outLength);
if (rv != 0) {
if (DEBUG) printf("ucryptoEncryptUpdate: ret = 0x%x\n", rv);
if (rv) {
if (DEBUG) printError("ucryptoEncryptUpdate", -1, rv);
} else {
*outLen = (int)outLength;
}
} else {
rv = (*ftab->ucryptoDecryptUpdate)(context, (unsigned char*)(bufIn+inOfs), (size_t)inLen, (unsigned char*)(bufOut+outOfs), &outLength);
if (rv != 0) {
if (DEBUG) printf("ucryptoDecryptUpdate: ret = 0x%x\n", rv);
if (rv) {
if (DEBUG) printError("ucryptoDecryptUpdate", -1, rv);
} else {
if (DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength);
*outLen = (int)outLength;
@ -263,16 +289,16 @@ CipherFinal(crypto_ctx_t *context, int encrypt, unsigned char *bufOut, int outOf
if (DEBUG) printf("CipherFinal: OutOfs %i, outLen %i\n", outOfs, *outLen);
if (encrypt) {
rv = (*ftab->ucryptoEncryptFinal)(context, (unsigned char*)(bufOut+outOfs), &outLength);
if (rv != 0) {
if (DEBUG) printf("ucryptoDecryptFinal: ret = 0x%x\n", rv);
if (rv) {
if (DEBUG) printError("ucryptoDecryptFinal", -1, rv);
} else {
if (DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength);
*outLen = (int)outLength;
}
} else {
rv = (*ftab->ucryptoDecryptFinal)(context, (unsigned char*)(bufOut+outOfs), &outLength);
if (rv != 0) {
if (DEBUG) printf("ucryptoDecryptFinal: ret = 0x%x\n", rv);
if (rv) {
if (DEBUG) printError("ucryptoDecryptFinal", -1, rv);
} else {
if (DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength);
*outLen = (int)outLength;
@ -285,102 +311,61 @@ CipherFinal(crypto_ctx_t *context, int encrypt, unsigned char *bufOut, int outOf
// SPECIAL ENTRIES FOR JVM JNI-BYPASSING OPTIMIZATION
////////////////////////////////////////////////////////
jlong JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeInit(jint mech) {
void *pContext = NULL;
crypto_ctx_t *context = NULL;
int rv;
switch (mech) {
case com_oracle_security_ucrypto_NativeDigest_MECH_SHA1:
pContext = (SHA1_CTX *) malloc(sizeof(SHA1_CTX));
if (pContext != NULL) {
(*ftab->sha1Init)((SHA1_CTX *)pContext);
context = malloc(sizeof(crypto_ctx_t));
if (context != NULL) {
rv = (*ftab->ucryptoDigestInit)(context, (ucrypto_mech_t) mech, NULL, 0);
if (rv) {
freeContext(context);
if (DEBUG) printError("ucryptoDigestInit", mech, rv);
return 0L;
}
break;
case com_oracle_security_ucrypto_NativeDigest_MECH_MD5:
pContext = (MD5_CTX *) malloc(sizeof(MD5_CTX));
if (pContext != NULL) {
(*ftab->md5Init)((MD5_CTX *)pContext);
}
break;
case com_oracle_security_ucrypto_NativeDigest_MECH_SHA256:
pContext = (SHA2_CTX *) malloc(sizeof(SHA2_CTX));
if (pContext != NULL) {
(*ftab->sha2Init)(SHA256, (SHA2_CTX *)pContext);
}
break;
case com_oracle_security_ucrypto_NativeDigest_MECH_SHA384:
pContext = (SHA2_CTX *) malloc(sizeof(SHA2_CTX));
if (pContext != NULL) {
(*ftab->sha2Init)(SHA384, (SHA2_CTX *)pContext);
}
break;
case com_oracle_security_ucrypto_NativeDigest_MECH_SHA512:
pContext = (SHA2_CTX *) malloc(sizeof(SHA2_CTX));
if (pContext != NULL) {
(*ftab->sha2Init)(SHA512, (SHA2_CTX *)pContext);
}
break;
default:
if (DEBUG) printf("ERROR: Unsupported mech %i\n", mech);
}
return (jlong) pContext;
return (jlong) context;
}
jint JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate
(jint mech, jlong pContext, int notUsed, unsigned char* in, jint ofs, jint len) {
if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) {
(*ftab->sha1Update)((SHA1_CTX*)pContext, (unsigned char*)(in+ofs), len);
} else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) {
(*ftab->md5Update)((MD5_CTX*)pContext, (unsigned char*)(in+ofs), len);
} else { // SHA-2 family
(*ftab->sha2Update)((SHA2_CTX*)pContext, (unsigned char*)(in+ofs), len);
crypto_ctx_t *context;
jint rv = 0;
context = (crypto_ctx_t *) pContext;
rv = (*ftab->ucryptoDigestUpdate)(context, (const unsigned char*)(in + ofs),
(size_t) len);
if (rv) {
freeContext(context);
if (DEBUG) printError("ucryptoDigestUpdate", mech, rv);
}
return 0;
return -rv; // use negative value to indicate error
}
// Do digest and free the context immediately
jint JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest
(jint mech, jlong pContext, int notUsed, unsigned char* out, jint ofs, jint digestLen) {
crypto_ctx_t *context;
jint rv = 0;
size_t digest_len = digestLen;
if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) {
(*ftab->sha1Final)((unsigned char*)(out + ofs), (SHA1_CTX *)pContext);
free((SHA1_CTX *)pContext);
} else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) {
(*ftab->md5Final)((unsigned char*)(out + ofs), (MD5_CTX *)pContext);
free((MD5_CTX *)pContext);
} else { // SHA-2 family
(*ftab->sha2Final)((unsigned char*)(out + ofs), (SHA2_CTX *)pContext);
free((SHA2_CTX *)pContext);
context = (crypto_ctx_t *) pContext;
rv = (*ftab->ucryptoDigestFinal)(context, (unsigned char*)(out + ofs),
&digest_len);
if (rv) {
freeContext(context);
if (DEBUG) printError("ucryptoDigestFinal", mech, rv);
}
return 0;
}
jlong JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeClone
(jint mech, jlong pContext) {
void *copy = NULL;
size_t len = 0;
if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) {
len = sizeof(SHA1_CTX);
} else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) {
len = sizeof(MD5_CTX);
} else { // SHA-2 family
len = sizeof(SHA2_CTX);
}
copy = (void*) malloc(len);
if (copy != NULL) {
bcopy((void *)pContext, copy, len);
}
return (jlong) copy;
return -rv; // use negative value to indicate error
}
void JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeFree
(jint mech, jlong pContext) {
if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) {
free((SHA1_CTX*) pContext);
} else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) {
free((MD5_CTX*) pContext);
} else { // SHA-2 family
free((SHA2_CTX*) pContext);
}
crypto_ctx_t *context;
context = (crypto_ctx_t *) pContext;
freeContext(context);
}
// AES
@ -395,7 +380,7 @@ jlong JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeInit
rv = CipherInit(context, encrypt, (ucrypto_mech_t) mech, bufKey, keyLen,
bufIv, ivLen, tagLen, bufAad, aadLen);
if (rv) {
free(context);
freeContext(context);
return 0L;
}
}
@ -417,8 +402,7 @@ jint JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeUpdate
context = (crypto_ctx_t *) pContext;
rv = CipherUpdate(context, encrypt, (unsigned char*)bufIn, inOfs, inLen, (unsigned char*)bufOut, outOfs, &outLen);
if (rv) {
free(context);
context = 0;
freeContext(context);
return -rv; // use negative value to indicate error!
}
@ -443,7 +427,7 @@ jint JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeFinal
outLen = 0;
}
rv = CipherFinal(context, encrypt, bufOut, outOfs, &outLen);
free(context);
freeContext(context);
if (rv) {
return -rv; // use negative value to indicate error!
}
@ -451,8 +435,6 @@ jint JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeFinal
return outLen;
}
/*
* Class: com_oracle_security_ucrypto_NativeDigest
* Method: nativeInit
@ -475,13 +457,15 @@ JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeInit
JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeUpdate
(JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jIn, jint jOfs, jint jLen) {
unsigned char *bufIn;
jint rv = 0;
bufIn = (unsigned char *) getBytes(env, jIn, jOfs, jLen);
if (!(*env)->ExceptionCheck(env)) {
JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate(mech, pContext, jLen, bufIn, 0, jLen);
rv = JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate(mech, pContext, jLen, bufIn, 0, jLen);
free(bufIn);
}
return 0;
return rv;
}
/*
@ -492,6 +476,7 @@ JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeUpdat
JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeDigest
(JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jOut, jint jOutOfs, jint digestLen) {
unsigned char *bufOut;
jint rv = 0;
bufOut = (unsigned char *) malloc(digestLen);
if (bufOut == NULL) {
@ -499,21 +484,12 @@ JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeDiges
return 0;
}
JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest(mech, pContext, digestLen, bufOut, 0, digestLen);
(*env)->SetByteArrayRegion(env, jOut, jOutOfs, digestLen, (jbyte *) bufOut);
rv = JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest(mech, pContext, digestLen, bufOut, 0, digestLen);
if (rv == 0) {
(*env)->SetByteArrayRegion(env, jOut, jOutOfs, digestLen, (jbyte *) bufOut);
}
free(bufOut);
return 0;
}
/*
* Class: com_oracle_security_ucrypto_NativeDigest
* Method: nativeClone
* Signature: (IJ)J
*/
JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeClone
(JNIEnv *env, jclass jcls, jint mech, jlong pContext) {
return JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeClone(mech, pContext);
return rv;
}
/*
@ -582,7 +558,7 @@ JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeCipher_nativeInit
cleanup:
if ((result == 0L) && (context != NULL)) {
free(context);
freeContext(context);
}
if (bufKey != NULL) {
(*env)->ReleaseByteArrayElements(env, jKey, (jbyte *)bufKey, 0);
@ -626,7 +602,7 @@ JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeCipher_nativeUpdat
rv = CipherUpdate(context, encrypt, bufIn, 0, inLen, bufOut, 0, &outLen);
if (rv) {
free(context);
freeContext(context);
free(bufIn);
free(bufOut);
return -rv;
@ -683,6 +659,7 @@ JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeCipher_nativeFinal
return rc;
}
/*
* Class: com_oracle_security_ucrypto_NativeKey
* Method: nativeFree
@ -984,9 +961,9 @@ jlong JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeIn
}
if (DEBUG) {
printf("RSAPublicKey Init: keyValue=%ld, keyLen=2\n", pKey);
printBytes("RSA PublicKey mod: ", (unsigned char*) mod, modLen);
printBytes("RSA PublicKey pubExp: ", (unsigned char*) pub, pubLen);
printf("RSAPublicKey.nativeInit: keyValue=%ld, keyLen=2\n", pKey);
printBytes("\tmod: ", (unsigned char*) mod, modLen);
printBytes("\tpubExp: ", (unsigned char*) pub, pubLen);
}
pKey[0].oa_type = SUN_CKA_MODULUS;
@ -1062,7 +1039,7 @@ SignatureInit(crypto_ctx_t *context, jint mechVal, jboolean sign,
if (DEBUG) {
printf("SignatureInit: context=%ld, mech=%d, sign=%d, keyValue=%ld, keyLength=%d\n",
context, mech, sign, pKey, keyLength);
printf("SignatureInit, ret => 0x%x\n", rv);
printError("SignatureInit", mech, rv);
}
return rv;
}
@ -1083,7 +1060,7 @@ jlong JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeInit
pKey = (uchar_t *) jKey;
rv = SignatureInit(context, mech, sign, pKey, (size_t)keyLength);
if (rv) {
free(context);
freeContext(context);
return 0L;
}
}
@ -1105,7 +1082,7 @@ JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeRSASignature_nati
pKey = (uchar_t *) jKey;
rv = SignatureInit(context, mech, sign, pKey, (size_t)keyLength);
if (rv) {
free(context);
freeContext(context);
throwUCExceptionUsingRV(env, rv);
return 0L;
}
@ -1125,7 +1102,7 @@ jint JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__J
context = (crypto_ctx_t *) pCtxt;
if (DEBUG) {
printf("Signature update: context=%ld, sign=%d, jIn=%ld, jInOfs=%d, jInLen=%d\n",
printf("NativeRSASignature.nativeUpdate: context=%ld, sign=%d, jIn=%ld, jInOfs=%d, jInLen=%d\n",
context, sign, jIn, jInOfs, jInLen);
}
if (sign) {
@ -1133,9 +1110,9 @@ jint JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__J
} else {
rv = (*ftab->ucryptoVerifyUpdate)(context, (uchar_t *) (jIn + jInOfs), (size_t) jInLen);
}
if (DEBUG) printf("Signature update, ret => 0x%x\n", rv);
if (rv) {
free(context);
freeContext(context);
if (DEBUG) printError("NativeRSASignature.nativeUpdate", -1, rv);
return -rv; // use negative value to indicate error!
}
@ -1194,9 +1171,9 @@ jint JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal
context = (crypto_ctx_t *) pCtxt;
if (DEBUG) {
printf("Signature final: context=%ld, sign=%d, bufSig=%ld, sigOfs=%d, sigLen=%d\n",
printf("NativeRSASignature.nativeFinal: context=%ld, sign=%d, bufSig=%ld, sigOfs=%d, sigLen=%d\n",
context, sign, bufSig, sigOfs, jSigLen);
printBytes("Before Final: SigBytes ", (unsigned char*) (bufSig + sigOfs), jSigLen);
printBytes("Before: SigBytes ", (unsigned char*) (bufSig + sigOfs), jSigLen);
}
if (sign) {
rv = (*ftab->ucryptoSignFinal)(context, (uchar_t *) (bufSig + sigOfs), &sigLength);
@ -1204,18 +1181,17 @@ jint JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal
rv = (*ftab->ucryptoVerifyFinal)(context, (uchar_t *) (bufSig + sigOfs), &sigLength);
}
if (DEBUG) {
printf("Signature nativeFinal, ret => 0x%x\n", rv);
if (sigLength != jSigLen) {
printf("SIG actual output len=%d\n", sigLength);
}
if (sign) {
printBytes("After nativeFinal: ", (unsigned char*) (bufSig + sigOfs), jSigLen);
}
}
free(context);
freeContext(context);
if (rv) {
if (DEBUG) {
printError("NativeRSASignature.nativeFinal", -1, rv);
if (sigLength != jSigLen) {
printf("NativeRSASignature.nativeFinal out sig len=%d\n", sigLength);
}
if (sign) {
printBytes("After: SigBytes ", (unsigned char*) (bufSig + sigOfs), jSigLen);
}
}
return -rv;
} else return 0;
}
@ -1273,10 +1249,10 @@ jint JavaCritical_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic
pKey = (uchar_t *) keyValue;
if (DEBUG) {
printf("Cipher nativeAtomic: mech=%d, encrypt=%d, pKey=%ld, keyLength=%d\n",
printf("NativeRSACipher.nativeAtomic: mech=%d, encrypt=%d, pKey=%ld, keyLength=%d\n",
mech, encrypt, pKey, keyLength);
printBytes("Before nativeAtomic: in: ", (unsigned char*) bufIn, jInLen);
printBytes("Before nativeAtomic: out: ", (unsigned char*) (bufOut + jOutOfs), jOutLen);
printBytes("Before: in = ", (unsigned char*) bufIn, jInLen);
printBytes("Before: out = ", (unsigned char*) (bufOut + jOutOfs), jOutLen);
}
if (encrypt) {
@ -1289,11 +1265,11 @@ jint JavaCritical_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic
(uchar_t *)(bufOut + jOutOfs), &outLength);
}
if (DEBUG) {
printf("Cipher nativeAtomic, ret => 0x%x\n", rv);
printError("NativeRSACipher.nativeAtomic", mech, rv);
if (outLength != jOutLen) {
printf("CIP actual output len=%d\n", outLength);
printf("NativeRSACipher.nativeAtomic out len=%d\n", outLength);
}
printBytes("After nativeAtomic: ", (unsigned char*) (bufOut + jOutOfs), outLength);
printBytes("After: ", (unsigned char*) (bufOut + jOutOfs), outLength);
}
if (rv) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2016, 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,18 +29,18 @@
extern "C" {
#endif
#undef com_oracle_security_ucrypto_NativeDigest_MECH_MD5
#define com_oracle_security_ucrypto_NativeDigest_MECH_MD5 1L
#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA1
#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA1 2L
#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA256
#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA256 3L
#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA224
#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA224 4L
#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA384
#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA384 5L
#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA512
#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA512 6L
#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5
#define com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5 1L
#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1
#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1 2L
#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA256
#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA256 3L
#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA224
#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA224 4L
#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA384
#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA384 5L
#undef com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA512
#define com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA512 6L
#define DEBUG 0

@ -0,0 +1,214 @@
/*
* Copyright (c) 2016, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <jni.h>
#include "jni_util.h"
#include <libsoftcrypto.h>
#include "nativeCrypto.h"
#include "nativeFunc.h"
extern void throwOutOfMemoryError(JNIEnv *env, const char *msg);
extern jbyte* getBytes(JNIEnv *env, jbyteArray bytes, int offset, int len);
///////////////////////////////////////////////////////
// SPECIAL ENTRIES FOR JVM JNI-BYPASSING OPTIMIZATION
////////////////////////////////////////////////////////
jlong JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeInit(jint mech) {
void *pContext = NULL;
switch (mech) {
case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1:
pContext = malloc(sizeof(SHA1_CTX));
if (pContext != NULL) {
(*ftab->sha1Init)((SHA1_CTX *)pContext);
}
break;
case com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5:
pContext = malloc(sizeof(MD5_CTX));
if (pContext != NULL) {
(*ftab->md5Init)((MD5_CTX *)pContext);
}
break;
case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA256:
pContext = malloc(sizeof(SHA2_CTX));
if (pContext != NULL) {
(*ftab->sha2Init)(SHA256, (SHA2_CTX *)pContext);
}
break;
case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA384:
pContext = malloc(sizeof(SHA2_CTX));
if (pContext != NULL) {
(*ftab->sha2Init)(SHA384, (SHA2_CTX *)pContext);
}
break;
case com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA512:
pContext = malloc(sizeof(SHA2_CTX));
if (pContext != NULL) {
(*ftab->sha2Init)(SHA512, (SHA2_CTX *)pContext);
}
break;
default:
if (DEBUG) printf("ERROR: Unsupported mech %i\n", mech);
}
return (jlong) pContext;
}
jint JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate
(jint mech, jlong pContext, int notUsed, unsigned char* in, jint ofs, jint len) {
if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
(*ftab->sha1Update)((SHA1_CTX*)pContext, (unsigned char*)(in+ofs), len);
} else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
(*ftab->md5Update)((MD5_CTX*)pContext, (unsigned char*)(in+ofs), len);
} else { // SHA-2 family
(*ftab->sha2Update)((SHA2_CTX*)pContext, (unsigned char*)(in+ofs), len);
}
return 0;
}
// Do digest and free the context immediately
jint JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest
(jint mech, jlong pContext, int notUsed, unsigned char* out, jint ofs, jint digestLen) {
if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
(*ftab->sha1Final)((unsigned char*)(out + ofs), (SHA1_CTX *)pContext);
free((SHA1_CTX *)pContext);
} else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
(*ftab->md5Final)((unsigned char*)(out + ofs), (MD5_CTX *)pContext);
free((MD5_CTX *)pContext);
} else { // SHA-2 family
(*ftab->sha2Final)((unsigned char*)(out + ofs), (SHA2_CTX *)pContext);
free((SHA2_CTX *)pContext);
}
return 0;
}
jlong JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeClone
(jint mech, jlong pContext) {
void *copy = NULL;
size_t len = 0;
if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
len = sizeof(SHA1_CTX);
} else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
len = sizeof(MD5_CTX);
} else { // SHA-2 family
len = sizeof(SHA2_CTX);
}
copy = malloc(len);
if (copy != NULL) {
bcopy((void *)pContext, copy, len);
}
return (jlong) copy;
}
void JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeFree
(jint mech, jlong pContext) {
if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_SHA1) {
free((SHA1_CTX*) pContext);
} else if (mech == com_oracle_security_ucrypto_NativeDigestMD_MECH_MD5) {
free((MD5_CTX*) pContext);
} else { // SHA-2 family
free((SHA2_CTX*) pContext);
}
}
/*
* Class: com_oracle_security_ucrypto_NativeDigestMD
* Method: nativeInit
* Signature: (I)J
*/
JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeInit
(JNIEnv *env, jclass jcls, jint mech) {
jlong result = JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeInit(mech);
if (result == NULL) {
throwOutOfMemoryError(env, NULL);
}
return result;
}
/*
* Class: com_oracle_security_ucrypto_NativeDigestMD
* Method: nativeUpdate
* Signature: (IJ[BII)I
*/
JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate
(JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jIn, jint jOfs, jint jLen) {
unsigned char *bufIn;
bufIn = (unsigned char *) getBytes(env, jIn, jOfs, jLen);
if (!(*env)->ExceptionCheck(env)) {
JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeUpdate(mech, pContext, jLen, bufIn, 0, jLen);
free(bufIn);
}
return 0;
}
/*
* Class: com_oracle_security_ucrypto_NativeDigestMD
* Method: nativeDigest
* Signature: (IJ[BII)I
*/
JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest
(JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jOut, jint jOutOfs, jint digestLen) {
unsigned char *bufOut;
bufOut = (unsigned char *) malloc(digestLen);
if (bufOut == NULL) {
throwOutOfMemoryError(env, NULL);
return 0;
}
JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeDigest(mech, pContext, digestLen, bufOut, 0, digestLen);
(*env)->SetByteArrayRegion(env, jOut, jOutOfs, digestLen, (jbyte *) bufOut);
free(bufOut);
return 0;
}
/*
* Class: com_oracle_security_ucrypto_NativeDigestMD
* Method: nativeClone
* Signature: (IJ)J
*/
JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeClone
(JNIEnv *env, jclass jcls, jint mech, jlong pContext) {
return JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeClone(mech, pContext);
}
/*
* Class: com_oracle_security_ucrypto_NativeDigestMD
* Method: nativeFree
* Signature: (IJ)V
*/
JNIEXPORT void JNICALL Java_com_oracle_security_ucrypto_NativeDigestMD_nativeFree
(JNIEnv *env, jclass jcls, jint mech, jlong pContext) {
JavaCritical_com_oracle_security_ucrypto_NativeDigestMD_nativeFree(mech, pContext);
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2016, 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
@ -42,21 +42,33 @@ static const char SHA2_UPDATE[] = "SHA2Update";
static const char SHA2_FINAL[] = "SHA2Final";
static const char UCRYPTO_VERSION[] = "ucrypto_version";
static const char UCRYPTO_GET_MECHLIST[] = "ucrypto_get_mechlist";
static const char UCRYPTO_ENCRYPT_INIT[] = "ucrypto_encrypt_init";
static const char UCRYPTO_ENCRYPT_UPDATE[] = "ucrypto_encrypt_update";
static const char UCRYPTO_ENCRYPT_FINAL[] = "ucrypto_encrypt_final";
static const char UCRYPTO_ENCRYPT[] = "ucrypto_encrypt";
static const char UCRYPTO_DECRYPT_INIT[] = "ucrypto_decrypt_init";
static const char UCRYPTO_DECRYPT_UPDATE[] = "ucrypto_decrypt_update";
static const char UCRYPTO_DECRYPT_FINAL[] = "ucrypto_decrypt_final";
static const char UCRYPTO_DECRYPT[] = "ucrypto_decrypt";
static const char UCRYPTO_SIGN_INIT[] = "ucrypto_sign_init";
static const char UCRYPTO_SIGN_UPDATE[] = "ucrypto_sign_update";
static const char UCRYPTO_SIGN_FINAL[] = "ucrypto_sign_final";
static const char UCRYPTO_VERIFY_INIT[] = "ucrypto_verify_init";
static const char UCRYPTO_VERIFY_UPDATE[] = "ucrypto_verify_update";
static const char UCRYPTO_VERIFY_FINAL[] = "ucrypto_verify_final";
static const char UCRYPTO_DIGEST_INIT[] = "ucrypto_digest_init";
static const char UCRYPTO_DIGEST_UPDATE[] = "ucrypto_digest_update";
static const char UCRYPTO_DIGEST_FINAL[] = "ucrypto_digest_final";
static const char UCRYPTO_FREE_CONTEXT[] = "ucrypto_free_context";
static const char UCRYPTO_STRERROR[] = "ucrypto_strerror";
/**
* Initialize native T4 crypto function pointers
*/
@ -73,28 +85,6 @@ jboolean* loadNative() {
return NULL;
}
lib = dlopen("libmd.so", RTLD_NOW);
if (lib != NULL) {
ftab->md5Init = (MD5INIT_FN_PTR) dlsym(lib, MD5_INIT);
ftab->md5Update = (MD5UPDATE_FN_PTR) dlsym(lib, MD5_UPDATE);
ftab->md5Final = (MD5FINAL_FN_PTR) dlsym(lib, MD5_FINAL);
ftab->sha1Init = (SHA1INIT_FN_PTR) dlsym(lib, SHA1_INIT);
ftab->sha1Update = (SHA1UPDATE_FN_PTR) dlsym(lib, SHA1_UPDATE);
ftab->sha1Final = (SHA1FINAL_FN_PTR) dlsym(lib, SHA1_FINAL);
ftab->sha2Init = (SHA2INIT_FN_PTR) dlsym(lib, SHA2_INIT);
ftab->sha2Update = (SHA2UPDATE_FN_PTR) dlsym(lib, SHA2_UPDATE);
ftab->sha2Final = (SHA2FINAL_FN_PTR) dlsym(lib, SHA2_FINAL);
if (ftab->md5Init != NULL && ftab->md5Update != NULL &&
ftab->md5Final != NULL && ftab->sha1Init != NULL &&
ftab->sha1Update != NULL && ftab->sha1Final != NULL &&
ftab->sha2Init != NULL && ftab->sha2Update != NULL &&
ftab->sha2Final != NULL) {
buf[0] = JNI_TRUE;
} else {
dlclose(lib);
}
}
lib = dlopen("libsoftcrypto.so", RTLD_NOW);
if (lib != NULL) {
// These APIs aren't available for v0 lib on Solaris 10
@ -102,7 +92,6 @@ jboolean* loadNative() {
dlsym(lib, UCRYPTO_VERSION);
ftab->ucryptoGetMechList = (UCRYPTO_GET_MECHLIST_FN_PTR)
dlsym(lib, UCRYPTO_GET_MECHLIST);
//??
ftab->ucryptoSignInit = (UCRYPTO_SIGN_INIT_FN_PTR)
dlsym(lib, UCRYPTO_SIGN_INIT);
ftab->ucryptoSignUpdate = (UCRYPTO_SIGN_UPDATE_FN_PTR)
@ -116,6 +105,21 @@ jboolean* loadNative() {
ftab->ucryptoVerifyFinal = (UCRYPTO_VERIFY_FINAL_FN_PTR)
dlsym(lib, UCRYPTO_VERIFY_FINAL);
// These APS are added starting S12
ftab->ucryptoDigestInit = (UCRYPTO_DIGEST_INIT_FN_PTR)
dlsym(lib, UCRYPTO_DIGEST_INIT);
ftab->ucryptoDigestUpdate = (UCRYPTO_DIGEST_UPDATE_FN_PTR)
dlsym(lib, UCRYPTO_DIGEST_UPDATE);
ftab->ucryptoDigestFinal = (UCRYPTO_DIGEST_FINAL_FN_PTR)
dlsym(lib, UCRYPTO_DIGEST_FINAL);
ftab->ucryptoFreeContext = (UCRYPTO_FREE_CONTEXT_FN_PTR)
dlsym(lib, UCRYPTO_FREE_CONTEXT);
ftab->ucryptoStrerror = (UCRYPTO_STRERROR_FN_PTR)
dlsym(lib, UCRYPTO_STRERROR);
// These should be avilable for all libsoftcrypto libs
ftab->ucryptoEncryptInit = (UCRYPTO_ENCRYPT_INIT_FN_PTR)
dlsym(lib, UCRYPTO_ENCRYPT_INIT);
@ -147,6 +151,34 @@ jboolean* loadNative() {
} else {
dlclose(lib);
}
// proceed with libmd when libucrypto does not support digest operations
if (ftab->ucryptoDigestInit == NULL ||
ftab->ucryptoDigestUpdate == NULL ||
ftab->ucryptoDigestFinal == NULL) {
lib = dlopen("libmd.so", RTLD_NOW);
if (lib != NULL) {
ftab->md5Init = (MD5INIT_FN_PTR) dlsym(lib, MD5_INIT);
ftab->md5Update = (MD5UPDATE_FN_PTR) dlsym(lib, MD5_UPDATE);
ftab->md5Final = (MD5FINAL_FN_PTR) dlsym(lib, MD5_FINAL);
ftab->sha1Init = (SHA1INIT_FN_PTR) dlsym(lib, SHA1_INIT);
ftab->sha1Update = (SHA1UPDATE_FN_PTR) dlsym(lib, SHA1_UPDATE);
ftab->sha1Final = (SHA1FINAL_FN_PTR) dlsym(lib, SHA1_FINAL);
ftab->sha2Init = (SHA2INIT_FN_PTR) dlsym(lib, SHA2_INIT);
ftab->sha2Update = (SHA2UPDATE_FN_PTR) dlsym(lib, SHA2_UPDATE);
ftab->sha2Final = (SHA2FINAL_FN_PTR) dlsym(lib, SHA2_FINAL);
if (ftab->md5Init != NULL && ftab->md5Update != NULL &&
ftab->md5Final != NULL && ftab->sha1Init != NULL &&
ftab->sha1Update != NULL && ftab->sha1Final != NULL &&
ftab->sha2Init != NULL && ftab->sha2Update != NULL &&
ftab->sha2Final != NULL) {
buf[0] = JNI_TRUE;
} else {
dlclose(lib);
}
}
}
}
return buf;

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2016, 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
@ -69,15 +69,12 @@ typedef int (*UCRYPTO_ENCRYPT_INIT_FN_PTR)
(crypto_ctx_t *context, ucrypto_mech_t mech_type,
uchar_t *key_str, size_t key_len,
void *iv, size_t iv_len);
typedef int (*UCRYPTO_ENCRYPT_UPDATE_FN_PTR)
(crypto_ctx_t *context, uchar_t *in,
size_t in_len, uchar_t *out, size_t *out_len);
typedef int (*UCRYPTO_ENCRYPT_FINAL_FN_PTR)
(crypto_ctx_t *context, uchar_t *out,
size_t *out_len);
typedef int (*UCRYPTO_ENCRYPT_FN_PTR)
(ucrypto_mech_t mech_type, uchar_t *key_str,
size_t key_len, void *iv, size_t iv_len, uchar_t *in,
@ -87,15 +84,12 @@ typedef int (*UCRYPTO_DECRYPT_INIT_FN_PTR)
(crypto_ctx_t *context,
ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len,
void *iv, size_t iv_len);
typedef int (*UCRYPTO_DECRYPT_UPDATE_FN_PTR)
(crypto_ctx_t *context, uchar_t *in,
size_t in_len, uchar_t *out, size_t *out_len);
typedef int (*UCRYPTO_DECRYPT_FINAL_FN_PTR)
(crypto_ctx_t *context, uchar_t *out,
size_t *out_len);
typedef int (*UCRYPTO_DECRYPT_FN_PTR)
(ucrypto_mech_t mech_type, uchar_t *key_str,
size_t key_len, void *iv, size_t iv_len, uchar_t *in,
@ -105,10 +99,8 @@ typedef int (*UCRYPTO_SIGN_INIT_FN_PTR)
(crypto_ctx_t *context, ucrypto_mech_t mech_type,
uchar_t *key_str, size_t key_len,
void *iv, size_t iv_len);
typedef int (*UCRYPTO_SIGN_UPDATE_FN_PTR)
(crypto_ctx_t *context, uchar_t *data_str, size_t data_len);
typedef int (*UCRYPTO_SIGN_FINAL_FN_PTR)
(crypto_ctx_t *context, uchar_t *sig_str, size_t *sig_len);
@ -116,13 +108,24 @@ typedef int (*UCRYPTO_VERIFY_INIT_FN_PTR)
(crypto_ctx_t *context, ucrypto_mech_t mech_type,
uchar_t *key_str, size_t key_len,
void *iv, size_t iv_len);
typedef int (*UCRYPTO_VERIFY_UPDATE_FN_PTR)
(crypto_ctx_t *context, uchar_t *data_str, size_t data_len);
typedef int (*UCRYPTO_VERIFY_FINAL_FN_PTR)
(crypto_ctx_t *context, uchar_t *sig_str, size_t *sig_len);
typedef int (*UCRYPTO_DIGEST_INIT_FN_PTR)
(crypto_ctx_t *context, ucrypto_mech_t mech_type,
void *param, size_t param_len);
typedef int (*UCRYPTO_DIGEST_UPDATE_FN_PTR)
(crypto_ctx_t *context, const uchar_t *data, size_t data_len);
typedef int (*UCRYPTO_DIGEST_FINAL_FN_PTR)
(crypto_ctx_t *context, uchar_t *digest, size_t *digest_len);
typedef void (*UCRYPTO_FREE_CONTEXT_FN_PTR)
(crypto_ctx_t *context);
typedef char* (*UCRYPTO_STRERROR_FN_PTR)(int rv);
/* dynamically resolved functions from libmd, and libsoftcrypto
@ -153,6 +156,11 @@ typedef struct T4CRYPTO_FUNCTION_TABLE {
UCRYPTO_VERIFY_INIT_FN_PTR ucryptoVerifyInit;
UCRYPTO_VERIFY_UPDATE_FN_PTR ucryptoVerifyUpdate;
UCRYPTO_VERIFY_FINAL_FN_PTR ucryptoVerifyFinal;
UCRYPTO_DIGEST_INIT_FN_PTR ucryptoDigestInit;
UCRYPTO_DIGEST_UPDATE_FN_PTR ucryptoDigestUpdate;
UCRYPTO_DIGEST_FINAL_FN_PTR ucryptoDigestFinal;
UCRYPTO_FREE_CONTEXT_FN_PTR ucryptoFreeContext;
UCRYPTO_STRERROR_FN_PTR ucryptoStrerror;
} T4CRYPTO_FUNCTION_TABLE;
typedef T4CRYPTO_FUNCTION_TABLE *T4CRYPTO_FUNCTION_TABLE_PTR;

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2016, 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
@ -23,7 +23,7 @@
/*
* @test
* @bug 7088989
* @bug 7088989 8000415
* @summary Ensure the various message digests works correctly
* @key randomness
*/
@ -40,84 +40,106 @@ public class TestDigest extends UcryptoTest {
private static final String[] MD_ALGOS = {
"MD5",
"SHA",
"SHA-224",
"SHA-256",
"SHA-384",
"SHA-512"
"SHA-512",
"SHA3-224",
"SHA3-256",
"SHA3-384",
"SHA3-512"
};
public static void main(String[] args) throws Exception {
main(new TestDigest(), null);
}
public void doTest(Provider p) {
public void doTest(Provider p) throws Exception {
boolean testPassed = true;
byte[] msg = new byte[200];
(new SecureRandom()).nextBytes(msg);
String interopProvName = "SUN";
MessageDigest md, md2;
for (String a : MD_ALGOS) {
System.out.println("Testing " + a);
try {
MessageDigest md, md2;
try {
md = MessageDigest.getInstance(a, p);
} catch (NoSuchAlgorithmException nsae) {
System.out.println("Skipping Unsupported MD algo: " + a);
continue;
}
md2 = MessageDigest.getInstance(a, interopProvName);
// Test Interoperability for update+digest calls
for (int i = 0; i < 3; i++) {
md.update(msg);
byte[] digest = md.digest();
md2.update(msg);
byte[] digest2 = md2.digest();
if (!Arrays.equals(digest, digest2)) {
System.out.println("DIFF1 FAILED for: " + a + " at iter " + i);
testPassed = false;
}
}
// Test Interoperability for digest calls
md = MessageDigest.getInstance(a, p);
} catch (NoSuchAlgorithmException nsae) {
System.out.println("=> Skip, unsupported");
continue;
}
try {
md2 = MessageDigest.getInstance(a, interopProvName);
} catch (NoSuchAlgorithmException nsae) {
System.out.println("=> Skip, no interop provider found");
continue;
}
for (int i = 0; i < 3; i++) {
byte[] digest = md.digest();
byte[] digest2 = md2.digest();
if (!Arrays.equals(digest, digest2)) {
System.out.println("DIFF2 FAILED for: " + a + " at iter " + i);
testPassed = false;
}
// Test Interoperability for update+digest calls
for (int i = 0; i < 3; i++) {
md.update(msg);
byte[] digest = md.digest();
md2.update(msg);
byte[] digest2 = md2.digest();
if (!Arrays.equals(digest, digest2)) {
System.out.println("DIFF1 FAILED at iter " + i);
testPassed = false;
} else {
System.out.println("...diff1 test passed");
}
}
// Test Cloning functionality
md = MessageDigest.getInstance(a, p);
md2 = (MessageDigest) md.clone(); // clone right after construction
// Test Interoperability for digest calls
md = MessageDigest.getInstance(a, p);
md2 = MessageDigest.getInstance(a, interopProvName);
for (int i = 0; i < 3; i++) {
byte[] digest = md.digest();
byte[] digest2 = md2.digest();
if (!Arrays.equals(digest, digest2)) {
System.out.println("DIFF-3.1 FAILED for: " + a);
System.out.println("DIFF2 FAILED at iter " + i);
testPassed = false;
} else {
System.out.println("...diff2 test passed");
}
md.update(msg);
md2 = (MessageDigest) md.clone(); // clone again after update call
digest = md.digest();
digest2 = md2.digest();
if (!Arrays.equals(digest, digest2)) {
System.out.println("DIFF-3.2 FAILED for: " + a);
testPassed = false;
}
md2 = (MessageDigest) md.clone(); // clone after digest
digest = md.digest();
digest2 = md2.digest();
if (!Arrays.equals(digest, digest2)) {
System.out.println("DIFF-3.3 FAILED for: " + a);
testPassed = false;
}
} catch(Exception ex) {
System.out.println("Unexpected Exception: " + a);
ex.printStackTrace();
}
// Test Cloning functionality if supported
md = MessageDigest.getInstance(a, p);
try {
md2 = (MessageDigest) md.clone(); // clone right after construction
} catch (CloneNotSupportedException cnse) {
System.out.println("...no clone support");
continue;
}
byte[] digest = md.digest();
byte[] digest2 = md2.digest();
if (!Arrays.equals(digest, digest2)) {
System.out.println("DIFF-3.1 FAILED");
testPassed = false;
} else {
System.out.println("...diff3.1 tests passed");
}
md.update(msg);
md2 = (MessageDigest) md.clone(); // clone again after update call
digest = md.digest();
digest2 = md2.digest();
if (!Arrays.equals(digest, digest2)) {
System.out.println("DIFF-3.2 FAILED");
testPassed = false;
} else {
System.out.println("...diff3.2 tests passed");
}
md2 = (MessageDigest) md.clone(); // clone after digest
digest = md.digest();
digest2 = md2.digest();
if (!Arrays.equals(digest, digest2)) {
System.out.println("DIFF-3.3 FAILED");
testPassed = false;
} else {
System.out.println("...diff3.3 tests passed");
}
}
if (!testPassed) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2016, 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
@ -84,6 +84,10 @@ public class Offsets {
test("SHA-256", 0, 64, 0, 128);
test("SHA-384", 0, 128, 0, 256);
test("SHA-512", 0, 128, 0, 256);
test("SHA3-224", 0, 64, 0, 128);
test("SHA3-256", 0, 64, 0, 128);
test("SHA3-384", 0, 128, 0, 256);
test("SHA3-512", 0, 128, 0, 256);
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2016, 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
@ -32,8 +32,13 @@ import java.util.*;
public class TestSHAClone {
// OracleUcrypto provider gets its digest impl from either
// libucrypto (starting S12 with SHA-3 support added) and
// libmd (pre-S12, no SHA-3 at all).
// The impls from libucrypto does not support clone but ones
// from libmd do.
private static final String[] ALGOS = {
"SHA", "SHA-224", "SHA-256", "SHA-512", "SHA-384"
"SHA", "SHA-224", "SHA-256", "SHA-384", "SHA-512"
};
private static byte[] input1 = {
@ -52,7 +57,13 @@ public class TestSHAClone {
private void run() throws Exception {
md.update(input1);
MessageDigest md2 = (MessageDigest) md.clone();
MessageDigest md2;
try {
md2 = (MessageDigest) md.clone();
} catch (CloneNotSupportedException cnse) {
System.out.println(md.getAlgorithm() + ": clone unsupported");
return;
}
md.update(input2);
md2.update(input2);
if (!Arrays.equals(md.digest(), md2.digest())) {