Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
de5cc3f6
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
de5cc3f6
编写于
1月 07, 2013
作者:
V
valeriep
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
6996769: support AEAD cipher
Summary: Added implementation for GCM mode under AES cipher Reviewed-by: weijun
上级
4e886604
变更
18
展开全部
隐藏空白更改
内联
并排
Showing
18 changed file
with
2009 addition
and
204 deletion
+2009
-204
src/share/classes/com/sun/crypto/provider/AESCipher.java
src/share/classes/com/sun/crypto/provider/AESCipher.java
+92
-1
src/share/classes/com/sun/crypto/provider/CipherCore.java
src/share/classes/com/sun/crypto/provider/CipherCore.java
+320
-123
src/share/classes/com/sun/crypto/provider/CipherTextStealing.java
...e/classes/com/sun/crypto/provider/CipherTextStealing.java
+9
-5
src/share/classes/com/sun/crypto/provider/FeedbackCipher.java
...share/classes/com/sun/crypto/provider/FeedbackCipher.java
+39
-7
src/share/classes/com/sun/crypto/provider/GCMParameters.java
src/share/classes/com/sun/crypto/provider/GCMParameters.java
+146
-0
src/share/classes/com/sun/crypto/provider/GCTR.java
src/share/classes/com/sun/crypto/provider/GCTR.java
+144
-0
src/share/classes/com/sun/crypto/provider/GHASH.java
src/share/classes/com/sun/crypto/provider/GHASH.java
+178
-0
src/share/classes/com/sun/crypto/provider/GaloisCounterMode.java
...re/classes/com/sun/crypto/provider/GaloisCounterMode.java
+501
-0
src/share/classes/com/sun/crypto/provider/SunJCE.java
src/share/classes/com/sun/crypto/provider/SunJCE.java
+14
-3
src/share/classes/javax/crypto/Cipher.java
src/share/classes/javax/crypto/Cipher.java
+18
-5
src/share/classes/javax/crypto/spec/GCMParameterSpec.java
src/share/classes/javax/crypto/spec/GCMParameterSpec.java
+2
-2
test/com/sun/crypto/provider/Cipher/AES/Test4512524.java
test/com/sun/crypto/provider/Cipher/AES/Test4512524.java
+7
-10
test/com/sun/crypto/provider/Cipher/AES/Test4512704.java
test/com/sun/crypto/provider/Cipher/AES/Test4512704.java
+9
-14
test/com/sun/crypto/provider/Cipher/AES/Test4517355.java
test/com/sun/crypto/provider/Cipher/AES/Test4517355.java
+24
-20
test/com/sun/crypto/provider/Cipher/AES/Test4626070.java
test/com/sun/crypto/provider/Cipher/AES/Test4626070.java
+7
-13
test/com/sun/crypto/provider/Cipher/AES/TestGCMKeyAndIvCheck.java
.../sun/crypto/provider/Cipher/AES/TestGCMKeyAndIvCheck.java
+178
-0
test/com/sun/crypto/provider/Cipher/AES/TestKATForGCM.java
test/com/sun/crypto/provider/Cipher/AES/TestKATForGCM.java
+314
-0
test/javax/crypto/Cipher/GCMAPI.java
test/javax/crypto/Cipher/GCMAPI.java
+7
-1
未找到文件。
src/share/classes/com/sun/crypto/provider/AESCipher.java
浏览文件 @
de5cc3f6
/*
* Copyright (c) 2002, 201
2
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 201
3
, 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,6 +30,7 @@ import java.security.spec.*;
import
javax.crypto.*
;
import
javax.crypto.spec.*
;
import
javax.crypto.BadPaddingException
;
import
java.nio.ByteBuffer
;
/**
* This class implements the AES algorithm in its various modes
...
...
@@ -127,6 +128,21 @@ abstract class AESCipher extends CipherSpi {
super
(
32
,
"CFB"
,
"NOPADDING"
);
}
}
public
static
final
class
AES128_GCM_NoPadding
extends
OidImpl
{
public
AES128_GCM_NoPadding
()
{
super
(
16
,
"GCM"
,
"NOPADDING"
);
}
}
public
static
final
class
AES192_GCM_NoPadding
extends
OidImpl
{
public
AES192_GCM_NoPadding
()
{
super
(
24
,
"GCM"
,
"NOPADDING"
);
}
}
public
static
final
class
AES256_GCM_NoPadding
extends
OidImpl
{
public
AES256_GCM_NoPadding
()
{
super
(
32
,
"GCM"
,
"NOPADDING"
);
}
}
// utility method used by AESCipher and AESWrapCipher
static
final
void
checkKeySize
(
Key
key
,
int
fixedKeySize
)
...
...
@@ -531,4 +547,79 @@ abstract class AESCipher extends CipherSpi {
return
core
.
unwrap
(
wrappedKey
,
wrappedKeyAlgorithm
,
wrappedKeyType
);
}
/**
* Continues a multi-part update of the Additional Authentication
* Data (AAD), using a subset of the provided buffer.
* <p>
* Calls to this method provide AAD to the cipher when operating in
* modes such as AEAD (GCM/CCM). If this cipher is operating in
* either GCM or CCM mode, all AAD must be supplied before beginning
* operations on the ciphertext (via the {@code update} and {@code
* doFinal} methods).
*
* @param src the buffer containing the AAD
* @param offset the offset in {@code src} where the AAD input starts
* @param len the number of AAD bytes
*
* @throws IllegalStateException if this cipher is in a wrong state
* (e.g., has not been initialized), does not accept AAD, or if
* operating in either GCM or CCM mode and one of the {@code update}
* methods has already been called for the active
* encryption/decryption operation
* @throws UnsupportedOperationException if this method
* has not been overridden by an implementation
*
* @since 1.8
*/
@Override
protected
void
engineUpdateAAD
(
byte
[]
src
,
int
offset
,
int
len
)
{
core
.
updateAAD
(
src
,
offset
,
len
);
}
/**
* Continues a multi-part update of the Additional Authentication
* Data (AAD).
* <p>
* Calls to this method provide AAD to the cipher when operating in
* modes such as AEAD (GCM/CCM). If this cipher is operating in
* either GCM or CCM mode, all AAD must be supplied before beginning
* operations on the ciphertext (via the {@code update} and {@code
* doFinal} methods).
* <p>
* All {@code src.remaining()} bytes starting at
* {@code src.position()} are processed.
* Upon return, the input buffer's position will be equal
* to its limit; its limit will not have changed.
*
* @param src the buffer containing the AAD
*
* @throws IllegalStateException if this cipher is in a wrong state
* (e.g., has not been initialized), does not accept AAD, or if
* operating in either GCM or CCM mode and one of the {@code update}
* methods has already been called for the active
* encryption/decryption operation
* @throws UnsupportedOperationException if this method
* has not been overridden by an implementation
*
* @since 1.8
*/
@Override
protected
void
engineUpdateAAD
(
ByteBuffer
src
)
{
if
(
src
!=
null
)
{
int
aadLen
=
src
.
limit
()
-
src
.
position
();
if
(
aadLen
!=
0
)
{
if
(
src
.
hasArray
())
{
int
aadOfs
=
src
.
arrayOffset
()
+
src
.
position
();
core
.
updateAAD
(
src
.
array
(),
aadOfs
,
aadLen
);
src
.
position
(
src
.
limit
());
}
else
{
byte
[]
aad
=
new
byte
[
aadLen
];
src
.
get
(
aad
);
core
.
updateAAD
(
aad
,
0
,
aadLen
);
}
}
}
}
}
src/share/classes/com/sun/crypto/provider/CipherCore.java
浏览文件 @
de5cc3f6
此差异已折叠。
点击以展开。
src/share/classes/com/sun/crypto/provider/CipherTextStealing.java
浏览文件 @
de5cc3f6
/*
* Copyright (c) 2004, 20
07
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 20
13
, 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
...
...
@@ -83,9 +83,10 @@ final class CipherTextStealing extends CipherBlockChaining {
* @param plainLen the length of the input data
* @param cipher the buffer for the result
* @param cipherOffset the offset in <code>cipher</code>
* @return the number of bytes placed into <code>cipher</code>
*/
void
encryptFinal
(
byte
[]
plain
,
int
plainOffset
,
int
plainLen
,
byte
[]
cipher
,
int
cipherOffset
)
int
encryptFinal
(
byte
[]
plain
,
int
plainOffset
,
int
plainLen
,
byte
[]
cipher
,
int
cipherOffset
)
throws
IllegalBlockSizeException
{
if
(
plainLen
<
blockSize
)
{
...
...
@@ -134,6 +135,7 @@ final class CipherTextStealing extends CipherBlockChaining {
embeddedCipher
.
encryptBlock
(
tmp2
,
0
,
cipher
,
cipherOffset
);
}
}
return
plainLen
;
}
/**
...
...
@@ -158,9 +160,10 @@ final class CipherTextStealing extends CipherBlockChaining {
* @param cipherLen the length of the input data
* @param plain the buffer for the result
* @param plainOffset the offset in <code>plain</code>
* @return the number of bytes placed into <code>plain</code>
*/
void
decryptFinal
(
byte
[]
cipher
,
int
cipherOffset
,
int
cipherLen
,
byte
[]
plain
,
int
plainOffset
)
int
decryptFinal
(
byte
[]
cipher
,
int
cipherOffset
,
int
cipherLen
,
byte
[]
plain
,
int
plainOffset
)
throws
IllegalBlockSizeException
{
if
(
cipherLen
<
blockSize
)
{
throw
new
IllegalBlockSizeException
(
"input is too short!"
);
...
...
@@ -211,5 +214,6 @@ final class CipherTextStealing extends CipherBlockChaining {
}
}
}
return
cipherLen
;
}
}
src/share/classes/com/sun/crypto/provider/FeedbackCipher.java
浏览文件 @
de5cc3f6
/*
* Copyright (c) 1997, 20
07
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 20
13
, 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
...
...
@@ -26,7 +26,7 @@
package
com.sun.crypto.provider
;
import
java.security.InvalidKeyException
;
import
javax.crypto.
IllegalBlockSizeException
;
import
javax.crypto.
*
;
/**
* This class represents a block cipher in one of its modes. It wraps
...
...
@@ -150,11 +150,13 @@ abstract class FeedbackCipher {
* @param plainLen the length of the input data
* @param cipher the buffer for the encryption result
* @param cipherOffset the offset in <code>cipher</code>
* @return the number of bytes placed into <code>cipher</code>
*/
void
encryptFinal
(
byte
[]
plain
,
int
plainOffset
,
int
plainLen
,
byte
[]
cipher
,
int
cipherOffset
)
int
encryptFinal
(
byte
[]
plain
,
int
plainOffset
,
int
plainLen
,
byte
[]
cipher
,
int
cipherOffset
)
throws
IllegalBlockSizeException
{
encrypt
(
plain
,
plainOffset
,
plainLen
,
cipher
,
cipherOffset
);
return
plainLen
;
}
/**
* Performs decryption operation.
...
...
@@ -190,10 +192,40 @@ abstract class FeedbackCipher {
* @param cipherLen the length of the input data
* @param plain the buffer for the decryption result
* @param plainOffset the offset in <code>plain</code>
* @return the number of bytes placed into <code>plain</code>
*/
void
decryptFinal
(
byte
[]
cipher
,
int
cipherOffset
,
int
cipherLen
,
byte
[]
plain
,
int
plainOffset
)
throws
IllegalBlockSizeException
{
int
decryptFinal
(
byte
[]
cipher
,
int
cipherOffset
,
int
cipherLen
,
byte
[]
plain
,
int
plainOffset
)
throws
IllegalBlockSizeException
,
AEADBadTagException
{
decrypt
(
cipher
,
cipherOffset
,
cipherLen
,
plain
,
plainOffset
);
return
cipherLen
;
}
/**
* Continues a multi-part update of the Additional Authentication
* Data (AAD), using a subset of the provided buffer. If this
* cipher is operating in either GCM or CCM mode, all AAD must be
* supplied before beginning operations on the ciphertext (via the
* {@code update} and {@code doFinal} methods).
* <p>
* NOTE: Given most modes do not accept AAD, default impl for this
* method throws IllegalStateException.
*
* @param src the buffer containing the AAD
* @param offset the offset in {@code src} where the AAD input starts
* @param len the number of AAD bytes
*
* @throws IllegalStateException if this cipher is in a wrong state
* (e.g., has not been initialized), does not accept AAD, or if
* operating in either GCM or CCM mode and one of the {@code update}
* methods has already been called for the active
* encryption/decryption operation
* @throws UnsupportedOperationException if this method
* has not been overridden by an implementation
*
* @since 1.8
*/
void
updateAAD
(
byte
[]
src
,
int
offset
,
int
len
)
{
throw
new
IllegalStateException
(
"No AAD accepted"
);
}
}
src/share/classes/com/sun/crypto/provider/GCMParameters.java
0 → 100644
浏览文件 @
de5cc3f6
/*
* Copyright (c) 2013, 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.sun.crypto.provider
;
import
java.io.IOException
;
import
java.security.AlgorithmParametersSpi
;
import
java.security.spec.AlgorithmParameterSpec
;
import
java.security.spec.InvalidParameterSpecException
;
import
javax.crypto.spec.GCMParameterSpec
;
import
sun.misc.HexDumpEncoder
;
import
sun.security.util.*
;
/**
* This class implements the parameter set used with
* GCM encryption, which is defined in RFC 5084 as follows:
*
* <pre>
* GCMParameters ::= SEQUENCE {
* aes-iv OCTET STRING, -- recommended size is 12 octets
* aes-tLen AES-GCM-ICVlen DEFAULT 12 }
*
* AES-GCM-ICVlen ::= INTEGER (12 | 13 | 14 | 15 | 16)
*
* </pre>
*
* @author Valerie Peng
* @since 1.8
*/
public
final
class
GCMParameters
extends
AlgorithmParametersSpi
{
// the iv
private
byte
[]
iv
;
// the tag length in bytes
private
int
tLen
;
public
GCMParameters
()
{}
protected
void
engineInit
(
AlgorithmParameterSpec
paramSpec
)
throws
InvalidParameterSpecException
{
if
(!(
paramSpec
instanceof
GCMParameterSpec
))
{
throw
new
InvalidParameterSpecException
(
"Inappropriate parameter specification"
);
}
GCMParameterSpec
gps
=
(
GCMParameterSpec
)
paramSpec
;
// need to convert from bits to bytes for ASN.1 encoding
this
.
tLen
=
gps
.
getTLen
()/
8
;
this
.
iv
=
gps
.
getIV
();
}
protected
void
engineInit
(
byte
[]
encoded
)
throws
IOException
{
DerValue
val
=
new
DerValue
(
encoded
);
// check if IV or params
if
(
val
.
tag
==
DerValue
.
tag_Sequence
)
{
byte
[]
iv
=
val
.
data
.
getOctetString
();
int
tLen
;
if
(
val
.
data
.
available
()
!=
0
)
{
tLen
=
val
.
data
.
getInteger
();
if
(
tLen
<
12
||
tLen
>
16
)
{
throw
new
IOException
(
"GCM parameter parsing error: unsupported tag len: "
+
tLen
);
}
if
(
val
.
data
.
available
()
!=
0
)
{
throw
new
IOException
(
"GCM parameter parsing error: extra data"
);
}
}
else
{
tLen
=
12
;
}
this
.
iv
=
iv
.
clone
();
this
.
tLen
=
tLen
;
}
else
{
throw
new
IOException
(
"GCM parameter parsing error: no SEQ tag"
);
}
}
protected
void
engineInit
(
byte
[]
encoded
,
String
decodingMethod
)
throws
IOException
{
engineInit
(
encoded
);
}
protected
<
T
extends
AlgorithmParameterSpec
>
T
engineGetParameterSpec
(
Class
<
T
>
paramSpec
)
throws
InvalidParameterSpecException
{
if
(
GCMParameterSpec
.
class
.
isAssignableFrom
(
paramSpec
))
{
return
paramSpec
.
cast
(
new
GCMParameterSpec
(
tLen
*
8
,
iv
));
}
else
{
throw
new
InvalidParameterSpecException
(
"Inappropriate parameter specification"
);
}
}
protected
byte
[]
engineGetEncoded
()
throws
IOException
{
DerOutputStream
out
=
new
DerOutputStream
();
DerOutputStream
bytes
=
new
DerOutputStream
();
bytes
.
putOctetString
(
iv
);
bytes
.
putInteger
(
tLen
);
out
.
write
(
DerValue
.
tag_Sequence
,
bytes
);
return
out
.
toByteArray
();
}
protected
byte
[]
engineGetEncoded
(
String
encodingMethod
)
throws
IOException
{
return
engineGetEncoded
();
}
/*
* Returns a formatted string describing the parameters.
*/
protected
String
engineToString
()
{
String
LINE_SEP
=
System
.
getProperty
(
"line.separator"
);
HexDumpEncoder
encoder
=
new
HexDumpEncoder
();
StringBuilder
sb
=
new
StringBuilder
(
LINE_SEP
+
" iv:"
+
LINE_SEP
+
"["
+
encoder
.
encodeBuffer
(
iv
)
+
"]"
);
sb
.
append
(
LINE_SEP
+
"tLen(bits):"
+
LINE_SEP
+
tLen
*
8
+
LINE_SEP
);
return
sb
.
toString
();
}
}
src/share/classes/com/sun/crypto/provider/GCTR.java
0 → 100644
浏览文件 @
de5cc3f6
/*
* Copyright (c) 2013, 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.
*/
/*
* (C) Copyright IBM Corp. 2013
*/
package
com.sun.crypto.provider
;
import
java.security.*
;
import
javax.crypto.*
;
import
static
com
.
sun
.
crypto
.
provider
.
AESConstants
.
AES_BLOCK_SIZE
;
/**
* This class represents the GCTR function defined in NIST 800-38D
* under section 6.5. It needs to be constructed w/ an initialized
* cipher object, and initial counter block(ICB). Given an input X
* of arbitrary length, it processes and returns an output which has
* the same length as X.
*
* <p>This function is used in the implementation of GCM mode.
*
* @since 1.8
*/
final
class
GCTR
{
// these fields should not change after the object has been constructed
private
final
SymmetricCipher
aes
;
private
final
byte
[]
icb
;
// the current counter value
private
byte
[]
counter
;
// needed for save/restore calls
private
byte
[]
counterSave
;
// NOTE: cipher should already be initialized
GCTR
(
SymmetricCipher
cipher
,
byte
[]
initialCounterBlk
)
{
this
.
aes
=
cipher
;
this
.
icb
=
initialCounterBlk
;
this
.
counter
=
icb
.
clone
();
}
// input must be multiples of 128-bit blocks when calling update
int
update
(
byte
[]
in
,
int
inOfs
,
int
inLen
,
byte
[]
out
,
int
outOfs
)
{
if
(
inLen
-
inOfs
>
in
.
length
)
{
throw
new
RuntimeException
(
"input length out of bound"
);
}
if
(
inLen
<
0
||
inLen
%
AES_BLOCK_SIZE
!=
0
)
{
throw
new
RuntimeException
(
"input length unsupported"
);
}
if
(
out
.
length
-
outOfs
<
inLen
)
{
throw
new
RuntimeException
(
"output buffer too small"
);
}
byte
[]
encryptedCntr
=
new
byte
[
AES_BLOCK_SIZE
];
int
numOfCompleteBlocks
=
inLen
/
AES_BLOCK_SIZE
;
for
(
int
i
=
0
;
i
<
numOfCompleteBlocks
;
i
++)
{
aes
.
encryptBlock
(
counter
,
0
,
encryptedCntr
,
0
);
for
(
int
n
=
0
;
n
<
AES_BLOCK_SIZE
;
n
++)
{
int
index
=
(
i
*
AES_BLOCK_SIZE
+
n
);
out
[
outOfs
+
index
]
=
(
byte
)
((
in
[
inOfs
+
index
]
^
encryptedCntr
[
n
]));
}
GaloisCounterMode
.
increment32
(
counter
);
}
return
inLen
;
}
// input can be arbitrary size when calling doFinal
protected
int
doFinal
(
byte
[]
in
,
int
inOfs
,
int
inLen
,
byte
[]
out
,
int
outOfs
)
throws
IllegalBlockSizeException
{
try
{
if
(
inLen
<
0
)
{
throw
new
IllegalBlockSizeException
(
"Negative input size!"
);
}
else
if
(
inLen
>
0
)
{
int
lastBlockSize
=
inLen
%
AES_BLOCK_SIZE
;
// process the complete blocks first
update
(
in
,
inOfs
,
inLen
-
lastBlockSize
,
out
,
outOfs
);
if
(
lastBlockSize
!=
0
)
{
// do the last partial block
byte
[]
encryptedCntr
=
new
byte
[
AES_BLOCK_SIZE
];
aes
.
encryptBlock
(
counter
,
0
,
encryptedCntr
,
0
);
int
processed
=
inLen
-
lastBlockSize
;
for
(
int
n
=
0
;
n
<
lastBlockSize
;
n
++)
{
out
[
outOfs
+
processed
+
n
]
=
(
byte
)
((
in
[
inOfs
+
processed
+
n
]
^
encryptedCntr
[
n
]));
}
}
}
}
finally
{
reset
();
}
return
inLen
;
}
/**
* Resets the current counter to its initial value.
* This is used after the doFinal() is called so this object can be
* reused w/o explicit re-initialization.
*/
void
reset
()
{
System
.
arraycopy
(
icb
,
0
,
counter
,
0
,
icb
.
length
);
}
/**
* Save the current content of this object.
*/
void
save
()
{
this
.
counterSave
=
this
.
counter
.
clone
();
}
/**
* Restores the content of this object to the previous saved one.
*/
void
restore
()
{
this
.
counter
=
this
.
counterSave
;
}
}
src/share/classes/com/sun/crypto/provider/GHASH.java
0 → 100644
浏览文件 @
de5cc3f6
/*
* Copyright (c) 2013, 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.
*/
/*
* (C) Copyright IBM Corp. 2013
*/
package
com.sun.crypto.provider
;
import
java.util.Arrays
;
import
java.security.*
;
import
static
com
.
sun
.
crypto
.
provider
.
AESConstants
.
AES_BLOCK_SIZE
;
/**
* This class represents the GHASH function defined in NIST 800-38D
* under section 6.4. It needs to be constructed w/ a hash subkey, i.e.
* block H. Given input of 128-bit blocks, it will process and output
* a 128-bit block.
*
* <p>This function is used in the implementation of GCM mode.
*
* @since 1.8
*/
final
class
GHASH
{
private
static
final
byte
P128
=
(
byte
)
0xe1
;
//reduction polynomial
private
static
boolean
getBit
(
byte
[]
b
,
int
pos
)
{
int
p
=
pos
/
8
;
pos
%=
8
;
int
i
=
(
b
[
p
]
>>>
(
7
-
pos
))
&
1
;
return
i
!=
0
;
}
private
static
void
shift
(
byte
[]
b
)
{
byte
temp
,
temp2
;
temp2
=
0
;
for
(
int
i
=
0
;
i
<
b
.
length
;
i
++)
{
temp
=
(
byte
)
((
b
[
i
]
&
0x01
)
<<
7
);
b
[
i
]
=
(
byte
)
((
b
[
i
]
&
0xff
)
>>>
1
);
b
[
i
]
=
(
byte
)
(
b
[
i
]
|
temp2
);
temp2
=
temp
;
}
}
// Given block X and Y, returns the muliplication of X * Y
private
static
byte
[]
blockMult
(
byte
[]
x
,
byte
[]
y
)
{
if
(
x
.
length
!=
AES_BLOCK_SIZE
||
y
.
length
!=
AES_BLOCK_SIZE
)
{
throw
new
RuntimeException
(
"illegal input sizes"
);
}
byte
[]
z
=
new
byte
[
AES_BLOCK_SIZE
];
byte
[]
v
=
y
.
clone
();
// calculate Z1-Z127 and V1-V127
for
(
int
i
=
0
;
i
<
127
;
i
++)
{
// Zi+1 = Zi if bit i of x is 0
if
(
getBit
(
x
,
i
))
{
for
(
int
n
=
0
;
n
<
z
.
length
;
n
++)
{
z
[
n
]
^=
v
[
n
];
}
}
boolean
lastBitOfV
=
getBit
(
v
,
127
);
shift
(
v
);
if
(
lastBitOfV
)
v
[
0
]
^=
P128
;
}
// calculate Z128
if
(
getBit
(
x
,
127
))
{
for
(
int
n
=
0
;
n
<
z
.
length
;
n
++)
{
z
[
n
]
^=
v
[
n
];
}
}
return
z
;
}
// hash subkey H; should not change after the object has been constructed
private
final
byte
[]
subkeyH
;
// buffer for storing hash
private
byte
[]
state
;
// variables for save/restore calls
private
byte
[]
stateSave
=
null
;
/**
* Initializes the cipher in the specified mode with the given key
* and iv.
*
* @param subkeyH the hash subkey
*
* @exception ProviderException if the given key is inappropriate for
* initializing this digest
*/
GHASH
(
byte
[]
subkeyH
)
throws
ProviderException
{
if
((
subkeyH
==
null
)
||
subkeyH
.
length
!=
AES_BLOCK_SIZE
)
{
throw
new
ProviderException
(
"Internal error"
);
}
this
.
subkeyH
=
subkeyH
;
this
.
state
=
new
byte
[
AES_BLOCK_SIZE
];
}
/**
* Resets the GHASH object to its original state, i.e. blank w/
* the same subkey H. Used after digest() is called and to re-use
* this object for different data w/ the same H.
*/
void
reset
()
{
Arrays
.
fill
(
state
,
(
byte
)
0
);
}
/**
* Save the current snapshot of this GHASH object.
*/
void
save
()
{
stateSave
=
state
.
clone
();
}
/**
* Restores this object using the saved snapshot.
*/
void
restore
()
{
state
=
stateSave
;
}
private
void
processBlock
(
byte
[]
data
,
int
ofs
)
{
if
(
data
.
length
-
ofs
<
AES_BLOCK_SIZE
)
{
throw
new
RuntimeException
(
"need complete block"
);
}
for
(
int
n
=
0
;
n
<
state
.
length
;
n
++)
{
state
[
n
]
^=
data
[
ofs
+
n
];
}
state
=
blockMult
(
state
,
subkeyH
);
}
void
update
(
byte
[]
in
)
{
update
(
in
,
0
,
in
.
length
);
}
void
update
(
byte
[]
in
,
int
inOfs
,
int
inLen
)
{
if
(
inLen
-
inOfs
>
in
.
length
)
{
throw
new
RuntimeException
(
"input length out of bound"
);
}
if
(
inLen
%
AES_BLOCK_SIZE
!=
0
)
{
throw
new
RuntimeException
(
"input length unsupported"
);
}
for
(
int
i
=
inOfs
;
i
<
(
inOfs
+
inLen
);
i
+=
AES_BLOCK_SIZE
)
{
processBlock
(
in
,
i
);
}
}
byte
[]
digest
()
{
try
{
return
state
.
clone
();
}
finally
{
reset
();
}
}
}
src/share/classes/com/sun/crypto/provider/GaloisCounterMode.java
0 → 100644
浏览文件 @
de5cc3f6
/*
* Copyright (c) 2013, 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.S
*
* 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.sun.crypto.provider
;
import
java.util.Arrays
;
import
java.io.*
;
import
java.security.*
;
import
javax.crypto.*
;
import
static
com
.
sun
.
crypto
.
provider
.
AESConstants
.
AES_BLOCK_SIZE
;
/**
* This class represents ciphers in GaloisCounter (GCM) mode.
*
* <p>This mode currently should only be used w/ AES cipher.
* Although no checking is done here, caller should only
* pass AES Cipher to the constructor.
*
* <p>NOTE: This class does not deal with buffering or padding.
*
* @since 1.8
*/
final
class
GaloisCounterMode
extends
FeedbackCipher
{
static
int
DEFAULT_TAG_LEN
=
AES_BLOCK_SIZE
;
static
int
DEFAULT_IV_LEN
=
12
;
// in bytes
// buffer for AAD data; if null, meaning update has been called
private
ByteArrayOutputStream
aadBuffer
=
new
ByteArrayOutputStream
();
private
int
sizeOfAAD
=
0
;
// in bytes; need to convert to bits (default value 128) when needed
private
int
tagLenBytes
=
DEFAULT_TAG_LEN
;
// these following 2 fields can only be initialized after init() is
// called, e.g. after cipher key k is set, and STAY UNCHANGED
private
byte
[]
subkeyH
=
null
;
private
byte
[]
preCounterBlock
=
null
;
private
GCTR
gctrPAndC
=
null
;
private
GHASH
ghashAllToS
=
null
;
// length of total data, i.e. len(C)
private
int
processed
=
0
;
// additional variables for save/restore calls
private
byte
[]
aadBufferSave
=
null
;
private
int
sizeOfAADSave
=
0
;
private
int
processedSave
=
0
;
// value must be 16-byte long; used by GCTR and GHASH as well
static
void
increment32
(
byte
[]
value
)
{
if
(
value
.
length
!=
AES_BLOCK_SIZE
)
{
throw
new
RuntimeException
(
"Unexpected counter block length"
);
}
// start from last byte and only go over 4 bytes, i.e. total 32 bits
int
n
=
value
.
length
-
1
;
while
((
n
>=
value
.
length
-
4
)
&&
(++
value
[
n
]
==
0
))
{
n
--;
}
}
// ivLen in bits
private
static
byte
[]
getLengthBlock
(
int
ivLen
)
{
byte
[]
out
=
new
byte
[
AES_BLOCK_SIZE
];
out
[
12
]
=
(
byte
)(
ivLen
>>>
24
);
out
[
13
]
=
(
byte
)(
ivLen
>>>
16
);
out
[
14
]
=
(
byte
)(
ivLen
>>>
8
);
out
[
15
]
=
(
byte
)
ivLen
;
return
out
;
}
// aLen and cLen both in bits
private
static
byte
[]
getLengthBlock
(
int
aLen
,
int
cLen
)
{
byte
[]
out
=
new
byte
[
AES_BLOCK_SIZE
];
out
[
4
]
=
(
byte
)(
aLen
>>>
24
);
out
[
5
]
=
(
byte
)(
aLen
>>>
16
);
out
[
6
]
=
(
byte
)(
aLen
>>>
8
);
out
[
7
]
=
(
byte
)
aLen
;
out
[
12
]
=
(
byte
)(
cLen
>>>
24
);
out
[
13
]
=
(
byte
)(
cLen
>>>
16
);
out
[
14
]
=
(
byte
)(
cLen
>>>
8
);
out
[
15
]
=
(
byte
)
cLen
;
return
out
;
}
private
static
byte
[]
expandToOneBlock
(
byte
[]
in
,
int
inOfs
,
int
len
)
{
if
(
len
>
AES_BLOCK_SIZE
)
{
throw
new
ProviderException
(
"input "
+
len
+
" too long"
);
}
if
(
len
==
AES_BLOCK_SIZE
&&
inOfs
==
0
)
{
return
in
;
}
else
{
byte
[]
paddedIn
=
new
byte
[
AES_BLOCK_SIZE
];
System
.
arraycopy
(
in
,
inOfs
,
paddedIn
,
0
,
len
);
return
paddedIn
;
}
}
private
static
byte
[]
getJ0
(
byte
[]
iv
,
byte
[]
subkeyH
)
{
byte
[]
j0
;
if
(
iv
.
length
==
12
)
{
// 96 bits
j0
=
expandToOneBlock
(
iv
,
0
,
iv
.
length
);
j0
[
AES_BLOCK_SIZE
-
1
]
=
1
;
}
else
{
GHASH
g
=
new
GHASH
(
subkeyH
);
int
lastLen
=
iv
.
length
%
AES_BLOCK_SIZE
;
if
(
lastLen
!=
0
)
{
g
.
update
(
iv
,
0
,
iv
.
length
-
lastLen
);
byte
[]
padded
=
expandToOneBlock
(
iv
,
iv
.
length
-
lastLen
,
lastLen
);
g
.
update
(
padded
);
}
else
{
g
.
update
(
iv
);
}
byte
[]
lengthBlock
=
getLengthBlock
(
iv
.
length
*
8
);
g
.
update
(
lengthBlock
);
j0
=
g
.
digest
();
}
return
j0
;
}
GaloisCounterMode
(
SymmetricCipher
embeddedCipher
)
{
super
(
embeddedCipher
);
aadBuffer
=
new
ByteArrayOutputStream
();
}
/**
* Gets the name of the feedback mechanism
*
* @return the name of the feedback mechanism
*/
String
getFeedback
()
{
return
"GCM"
;
}
/**
* Resets the cipher object to its original state.
* This is used when doFinal is called in the Cipher class, so that the
* cipher can be reused (with its original key and iv).
*/
void
reset
()
{
if
(
aadBuffer
==
null
)
{
aadBuffer
=
new
ByteArrayOutputStream
();
}
else
{
aadBuffer
.
reset
();
}
if
(
gctrPAndC
!=
null
)
gctrPAndC
.
reset
();
if
(
ghashAllToS
!=
null
)
ghashAllToS
.
reset
();
processed
=
0
;
sizeOfAAD
=
0
;
}
/**
* Save the current content of this cipher.
*/
void
save
()
{
processedSave
=
processed
;
sizeOfAADSave
=
sizeOfAAD
;
aadBufferSave
=
((
aadBuffer
==
null
||
aadBuffer
.
size
()
==
0
)?
null
:
aadBuffer
.
toByteArray
());
if
(
gctrPAndC
!=
null
)
gctrPAndC
.
save
();
if
(
ghashAllToS
!=
null
)
ghashAllToS
.
save
();
}
/**
* Restores the content of this cipher to the previous saved one.
*/
void
restore
()
{
processed
=
processedSave
;
sizeOfAAD
=
sizeOfAADSave
;
if
(
aadBuffer
!=
null
)
{
aadBuffer
.
reset
();
if
(
aadBufferSave
!=
null
)
{
aadBuffer
.
write
(
aadBufferSave
,
0
,
aadBufferSave
.
length
);
}
}
if
(
gctrPAndC
!=
null
)
gctrPAndC
.
restore
();
if
(
ghashAllToS
!=
null
)
ghashAllToS
.
restore
();
}
/**
* Initializes the cipher in the specified mode with the given key
* and iv.
*
* @param decrypting flag indicating encryption or decryption
* @param algorithm the algorithm name
* @param key the key
* @param iv the iv
* @param tagLenBytes the length of tag in bytes
*
* @exception InvalidKeyException if the given key is inappropriate for
* initializing this cipher
*/
void
init
(
boolean
decrypting
,
String
algorithm
,
byte
[]
key
,
byte
[]
iv
)
throws
InvalidKeyException
{
init
(
decrypting
,
algorithm
,
key
,
iv
,
DEFAULT_TAG_LEN
);
}
/**
* Initializes the cipher in the specified mode with the given key
* and iv.
*
* @param decrypting flag indicating encryption or decryption
* @param algorithm the algorithm name
* @param key the key
* @param iv the iv
* @param tagLenBytes the length of tag in bytes
*
* @exception InvalidKeyException if the given key is inappropriate for
* initializing this cipher
*/
void
init
(
boolean
decrypting
,
String
algorithm
,
byte
[]
keyValue
,
byte
[]
ivValue
,
int
tagLenBytes
)
throws
InvalidKeyException
{
if
(
keyValue
==
null
||
ivValue
==
null
)
{
throw
new
InvalidKeyException
(
"Internal error"
);
}
// always encrypt mode for embedded cipher
this
.
embeddedCipher
.
init
(
false
,
algorithm
,
keyValue
);
this
.
subkeyH
=
new
byte
[
AES_BLOCK_SIZE
];
this
.
embeddedCipher
.
encryptBlock
(
new
byte
[
AES_BLOCK_SIZE
],
0
,
this
.
subkeyH
,
0
);
this
.
iv
=
ivValue
.
clone
();
preCounterBlock
=
getJ0
(
iv
,
subkeyH
);
byte
[]
j0Plus1
=
preCounterBlock
.
clone
();
increment32
(
j0Plus1
);
gctrPAndC
=
new
GCTR
(
embeddedCipher
,
j0Plus1
);
ghashAllToS
=
new
GHASH
(
subkeyH
);
this
.
tagLenBytes
=
tagLenBytes
;
if
(
aadBuffer
==
null
)
{
aadBuffer
=
new
ByteArrayOutputStream
();
}
else
{
aadBuffer
.
reset
();
}
processed
=
0
;
sizeOfAAD
=
0
;
}
/**
* Continues a multi-part update of the Additional Authentication
* Data (AAD), using a subset of the provided buffer. If this
* cipher is operating in either GCM or CCM mode, all AAD must be
* supplied before beginning operations on the ciphertext (via the
* {@code update} and {@code doFinal} methods).
* <p>
* NOTE: Given most modes do not accept AAD, default impl for this
* method throws IllegalStateException.
*
* @param src the buffer containing the AAD
* @param offset the offset in {@code src} where the AAD input starts
* @param len the number of AAD bytes
*
* @throws IllegalStateException if this cipher is in a wrong state
* (e.g., has not been initialized), does not accept AAD, or if
* operating in either GCM or CCM mode and one of the {@code update}
* methods has already been called for the active
* encryption/decryption operation
* @throws UnsupportedOperationException if this method
* has not been overridden by an implementation
*
* @since 1.8
*/
void
updateAAD
(
byte
[]
src
,
int
offset
,
int
len
)
{
if
(
aadBuffer
!=
null
)
{
aadBuffer
.
write
(
src
,
offset
,
len
);
}
else
{
// update has already been called
throw
new
IllegalStateException
(
"Update has been called; no more AAD data"
);
}
}
// Feed the AAD data to GHASH, pad if necessary
void
processAAD
()
{
if
(
aadBuffer
!=
null
)
{
byte
[]
aad
=
aadBuffer
.
toByteArray
();
sizeOfAAD
=
aad
.
length
;
aadBuffer
=
null
;
int
lastLen
=
aad
.
length
%
AES_BLOCK_SIZE
;
if
(
lastLen
!=
0
)
{
ghashAllToS
.
update
(
aad
,
0
,
aad
.
length
-
lastLen
);
byte
[]
padded
=
expandToOneBlock
(
aad
,
aad
.
length
-
lastLen
,
lastLen
);
ghashAllToS
.
update
(
padded
);
}
else
{
ghashAllToS
.
update
(
aad
);
}
}
}
// Utility to process the last block; used by encryptFinal and decryptFinal
void
doLastBlock
(
byte
[]
in
,
int
inOfs
,
int
len
,
byte
[]
out
,
int
outOfs
,
boolean
isEncrypt
)
throws
IllegalBlockSizeException
{
// process data in 'in'
gctrPAndC
.
doFinal
(
in
,
inOfs
,
len
,
out
,
outOfs
);
processed
+=
len
;
byte
[]
ct
;
int
ctOfs
;
if
(
isEncrypt
)
{
ct
=
out
;
ctOfs
=
outOfs
;
}
else
{
ct
=
in
;
ctOfs
=
inOfs
;
}
int
lastLen
=
len
%
AES_BLOCK_SIZE
;
if
(
lastLen
!=
0
)
{
ghashAllToS
.
update
(
ct
,
ctOfs
,
len
-
lastLen
);
byte
[]
padded
=
expandToOneBlock
(
ct
,
(
ctOfs
+
len
-
lastLen
),
lastLen
);
ghashAllToS
.
update
(
padded
);
}
else
{
ghashAllToS
.
update
(
ct
,
ctOfs
,
len
);
}
}
/**
* Performs encryption operation.
*
* <p>The input plain text <code>in</code>, starting at <code>inOff</code>
* and ending at <code>(inOff + len - 1)</code>, is encrypted. The result
* is stored in <code>out</code>, starting at <code>outOfs</code>.
*
* <p>It is the application's responsibility to make sure that
* <code>len</code> is a multiple of the embedded cipher's block size,
* otherwise, a ProviderException will be thrown.
*
* <p>It is also the application's responsibility to make sure that
* <code>init</code> has been called before this method is called.
* (This check is omitted here, to avoid double checking.)
*
* @param in the buffer with the input data to be encrypted
* @param inOfs the offset in <code>in</code>
* @param len the length of the input data
* @param out the buffer for the result
* @param outOfs the offset in <code>out</code>
*/
void
encrypt
(
byte
[]
in
,
int
inOfs
,
int
len
,
byte
[]
out
,
int
outOfs
)
{
processAAD
();
if
(
len
>
0
)
{
gctrPAndC
.
update
(
in
,
inOfs
,
len
,
out
,
outOfs
);
processed
+=
len
;
ghashAllToS
.
update
(
out
,
outOfs
,
len
);
}
}
/**
* Performs encryption operation for the last time.
*
* <p>NOTE: <code>len</code> may not be multiple of the embedded
* cipher's block size for this call.
*
* @param in the input buffer with the data to be encrypted
* @param inOfs the offset in <code>in</code>
* @param len the length of the input data
* @param out the buffer for the encryption result
* @param outOfs the offset in <code>out</code>
* @return the number of bytes placed into the <code>out</code> buffer
*/
int
encryptFinal
(
byte
[]
in
,
int
inOfs
,
int
len
,
byte
[]
out
,
int
outOfs
)
throws
IllegalBlockSizeException
{
if
(
out
.
length
-
outOfs
<
(
len
+
tagLenBytes
))
{
throw
new
RuntimeException
(
"Output buffer too small"
);
}
processAAD
();
if
(
len
>
0
)
{
//ByteUtil.dumpArray(Arrays.copyOfRange(in, inOfs, inOfs + len));
doLastBlock
(
in
,
inOfs
,
len
,
out
,
outOfs
,
true
);
}
byte
[]
lengthBlock
=
getLengthBlock
(
sizeOfAAD
*
8
,
processed
*
8
);
ghashAllToS
.
update
(
lengthBlock
);
byte
[]
s
=
ghashAllToS
.
digest
();
byte
[]
sOut
=
new
byte
[
s
.
length
];
GCTR
gctrForSToTag
=
new
GCTR
(
embeddedCipher
,
this
.
preCounterBlock
);
gctrForSToTag
.
doFinal
(
s
,
0
,
s
.
length
,
sOut
,
0
);
System
.
arraycopy
(
sOut
,
0
,
out
,
(
outOfs
+
len
),
tagLenBytes
);
return
(
len
+
tagLenBytes
);
}
/**
* Performs decryption operation.
*
* <p>The input cipher text <code>in</code>, starting at
* <code>inOfs</code> and ending at <code>(inOfs + len - 1)</code>,
* is decrypted. The result is stored in <code>out</code>, starting at
* <code>outOfs</code>.
*
* <p>It is the application's responsibility to make sure that
* <code>len</code> is a multiple of the embedded cipher's block
* size, as any excess bytes are ignored.
*
* <p>It is also the application's responsibility to make sure that
* <code>init</code> has been called before this method is called.
* (This check is omitted here, to avoid double checking.)
*
* @param in the buffer with the input data to be decrypted
* @param inOfs the offset in <code>in</code>
* @param len the length of the input data
* @param out the buffer for the result
* @param outOfs the offset in <code>out</code>
*/
void
decrypt
(
byte
[]
in
,
int
inOfs
,
int
len
,
byte
[]
out
,
int
outOfs
)
{
processAAD
();
if
(
len
>
0
)
{
// must be at least AES_BLOCK_SIZE bytes long
gctrPAndC
.
update
(
in
,
inOfs
,
len
,
out
,
outOfs
);
processed
+=
len
;
ghashAllToS
.
update
(
in
,
inOfs
,
len
);
}
}
/**
* Performs decryption operation for the last time.
*
* <p>NOTE: For cipher feedback modes which does not perform
* special handling for the last few blocks, this is essentially
* the same as <code>encrypt(...)</code>. Given most modes do
* not do special handling, the default impl for this method is
* to simply call <code>decrypt(...)</code>.
*
* @param in the input buffer with the data to be decrypted
* @param inOfs the offset in <code>cipher</code>
* @param len the length of the input data
* @param out the buffer for the decryption result
* @param outOfs the offset in <code>plain</code>
* @return the number of bytes placed into the <code>out</code> buffer
*/
int
decryptFinal
(
byte
[]
in
,
int
inOfs
,
int
len
,
byte
[]
out
,
int
outOfs
)
throws
IllegalBlockSizeException
,
AEADBadTagException
{
if
(
len
<
tagLenBytes
)
{
throw
new
RuntimeException
(
"Input buffer too short - need tag"
);
}
if
(
out
.
length
-
outOfs
<
(
len
-
tagLenBytes
))
{
throw
new
RuntimeException
(
"Output buffer too small"
);
}
processAAD
();
int
processedOld
=
processed
;
byte
[]
tag
=
new
byte
[
tagLenBytes
];
// get the trailing tag bytes from 'in'
System
.
arraycopy
(
in
,
inOfs
+
len
-
tagLenBytes
,
tag
,
0
,
tagLenBytes
);
len
-=
tagLenBytes
;
if
(
len
>
0
)
{
doLastBlock
(
in
,
inOfs
,
len
,
out
,
outOfs
,
false
);
}
byte
[]
lengthBlock
=
getLengthBlock
(
sizeOfAAD
*
8
,
processed
*
8
);
ghashAllToS
.
update
(
lengthBlock
);
byte
[]
s
=
ghashAllToS
.
digest
();
byte
[]
sOut
=
new
byte
[
s
.
length
];
GCTR
gctrForSToTag
=
new
GCTR
(
embeddedCipher
,
this
.
preCounterBlock
);
gctrForSToTag
.
doFinal
(
s
,
0
,
s
.
length
,
sOut
,
0
);
for
(
int
i
=
0
;
i
<
tagLenBytes
;
i
++)
{
if
(
tag
[
i
]
!=
sOut
[
i
])
{
throw
new
AEADBadTagException
(
"Tag mismatch!"
);
}
}
return
len
;
}
// return tag length in bytes
int
getTagLen
()
{
return
this
.
tagLenBytes
;
}
}
src/share/classes/com/sun/crypto/provider/SunJCE.java
浏览文件 @
de5cc3f6
/*
* Copyright (c) 1997, 201
2
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
3
, 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
...
...
@@ -57,6 +57,7 @@ import java.security.SecureRandom;
* - ARCFOUR (RC4 compatible)
*
* - Cipher modes ECB, CBC, CFB, OFB, PCBC, CTR, and CTS for all block ciphers
* and mode GCM for AES cipher
*
* - Cipher padding ISO10126Padding for non-PKCS#5 block ciphers and
* NoPadding and PKCS5Padding for all block ciphers
...
...
@@ -100,7 +101,7 @@ public final class SunJCE extends Provider {
"|CFB8|CFB16|CFB24|CFB32|CFB40|CFB48|CFB56|CFB64"
+
"|OFB8|OFB16|OFB24|OFB32|OFB40|OFB48|OFB56|OFB64"
;
final
String
BLOCK_MODES128
=
BLOCK_MODES
+
"|CFB72|CFB80|CFB88|CFB96|CFB104|CFB112|CFB120|CFB128"
+
"|
GCM|
CFB72|CFB80|CFB88|CFB96|CFB104|CFB112|CFB120|CFB128"
+
"|OFB72|OFB80|OFB88|OFB96|OFB104|OFB112|OFB120|OFB128"
;
final
String
BLOCK_PADS
=
"NOPADDING|PKCS5PADDING|ISO10126PADDING"
;
...
...
@@ -258,6 +259,9 @@ public final class SunJCE extends Provider {
put
(
"Cipher.AES_128/CFB/NoPadding"
,
"com.sun.crypto.provider.AESCipher$AES128_CFB_NoPadding"
);
put
(
"Alg.Alias.Cipher.2.16.840.1.101.3.4.1.4"
,
"AES_128/CFB/NoPadding"
);
put
(
"Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.4"
,
"AES_128/CFB/NoPadding"
);
put
(
"Cipher.AES_128/GCM/NoPadding"
,
"com.sun.crypto.provider.AESCipher$AES128_GCM_NoPadding"
);
put
(
"Alg.Alias.Cipher.2.16.840.1.101.3.4.1.6"
,
"AES_128/GCM/NoPadding"
);
put
(
"Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.6"
,
"AES_128/GCM/NoPadding"
);
put
(
"Cipher.AES_192/ECB/NoPadding"
,
"com.sun.crypto.provider.AESCipher$AES192_ECB_NoPadding"
);
put
(
"Alg.Alias.Cipher.2.16.840.1.101.3.4.1.21"
,
"AES_192/ECB/NoPadding"
);
...
...
@@ -271,7 +275,9 @@ public final class SunJCE extends Provider {
put
(
"Cipher.AES_192/CFB/NoPadding"
,
"com.sun.crypto.provider.AESCipher$AES192_CFB_NoPadding"
);
put
(
"Alg.Alias.Cipher.2.16.840.1.101.3.4.1.24"
,
"AES_192/CFB/NoPadding"
);
put
(
"Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.24"
,
"AES_192/CFB/NoPadding"
);
put
(
"Cipher.AES_192/GCM/NoPadding"
,
"com.sun.crypto.provider.AESCipher$AES192_GCM_NoPadding"
);
put
(
"Alg.Alias.Cipher.2.16.840.1.101.3.4.1.26"
,
"AES_192/GCM/NoPadding"
);
put
(
"Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.26"
,
"AES_192/GCM/NoPadding"
);
put
(
"Cipher.AES_256/ECB/NoPadding"
,
"com.sun.crypto.provider.AESCipher$AES256_ECB_NoPadding"
);
put
(
"Alg.Alias.Cipher.2.16.840.1.101.3.4.1.41"
,
"AES_256/ECB/NoPadding"
);
...
...
@@ -285,6 +291,9 @@ public final class SunJCE extends Provider {
put
(
"Cipher.AES_256/CFB/NoPadding"
,
"com.sun.crypto.provider.AESCipher$AES256_CFB_NoPadding"
);
put
(
"Alg.Alias.Cipher.2.16.840.1.101.3.4.1.44"
,
"AES_256/CFB/NoPadding"
);
put
(
"Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.44"
,
"AES_256/CFB/NoPadding"
);
put
(
"Cipher.AES_256/GCM/NoPadding"
,
"com.sun.crypto.provider.AESCipher$AES256_GCM_NoPadding"
);
put
(
"Alg.Alias.Cipher.2.16.840.1.101.3.4.1.46"
,
"AES_256/GCM/NoPadding"
);
put
(
"Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.46"
,
"AES_256/GCM/NoPadding"
);
put
(
"Cipher.AESWrap"
,
"com.sun.crypto.provider.AESWrapCipher$General"
);
put
(
"Cipher.AESWrap SupportedModes"
,
"ECB"
);
...
...
@@ -509,6 +518,8 @@ public final class SunJCE extends Provider {
put
(
"AlgorithmParameters.AES"
,
"com.sun.crypto.provider.AESParameters"
);
put
(
"Alg.Alias.AlgorithmParameters.Rijndael"
,
"AES"
);
put
(
"AlgorithmParameters.GCM"
,
"com.sun.crypto.provider.GCMParameters"
);
put
(
"AlgorithmParameters.RC2"
,
...
...
src/share/classes/javax/crypto/Cipher.java
浏览文件 @
de5cc3f6
/*
* Copyright (c) 1997, 201
2
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
3
, 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
...
...
@@ -104,17 +104,30 @@ import sun.security.jca.*;
* must be supplied to GCM/CCM implementations (via the {@code
* updateAAD} methods) <b>before</b> the ciphertext is processed (via
* the {@code update} and {@code doFinal} methods).
*
* <p>
* Note that GCM mode has a uniqueness requirement on IVs used in
* encryption with a given key. When IVs are repeated for GCM
* encryption, such usages are subject to forgery attacks. Thus, after
* each encryption operation using GCM mode, callers should re-initialize
* the cipher objects with GCM parameters which has a different IV value.
* <pre>
* GCMParameterSpec s =
new GCMParameterSpec(...)
;
* GCMParameterSpec s =
...
;
* cipher.init(..., s);
*
* // If the GCMParameterSpec is needed again
* cipher.getParameters().getParameterSpec(GCMParameterSpec.class));
* // If the GCM parameters were generated by the provider, it can
* // be retrieved by:
* // cipher.getParameters().getParameterSpec(GCMParameterSpec.class);
*
* cipher.updateAAD(...); // AAD
* cipher.update(...); // Multi-part update
* cipher.doFinal(...); // conclusion of operation
*
* // Use a different IV value for every encryption
* byte[] newIv = ...;
* s = new GCMParameterSpec(s.getTLen(), newIv);
* cipher.init(..., s);
* ...
*
* </pre>
* Every implementation of the Java platform is required to support
* the following standard <code>Cipher</code> transformations with the keysizes
...
...
src/share/classes/javax/crypto/spec/GCMParameterSpec.java
浏览文件 @
de5cc3f6
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011,
2013,
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
...
...
@@ -43,7 +43,7 @@ import java.security.spec.AlgorithmParameterSpec;
* (Additional Authenticated Data (AAD), Keys, block ciphers,
* plain/ciphertext and authentication tags) are handled in the {@code
* Cipher} class.
<p>
*
<p>
* Please see <a href="http://www.ietf.org/rfc/rfc5116.txt"> RFC 5116
* </a> for more information on the Authenticated Encryption with
* Associated Data (AEAD) algorithm, and <a href=
...
...
test/com/sun/crypto/provider/Cipher/AES/Test4512524.java
浏览文件 @
de5cc3f6
/*
* Copyright (c) 2002, 20
07
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 20
13
, 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
...
...
@@ -40,13 +40,13 @@ import com.sun.crypto.provider.*;
public
class
Test4512524
{
private
static
final
String
ALGO
=
"AES"
;
private
static
final
String
MODE
=
"CBC"
;
private
static
final
String
PADDING
=
"NoPadding"
;
private
static
final
int
KEYSIZE
=
16
;
// in bytes
public
boolean
execute
(
)
throws
Exception
{
public
void
execute
(
String
mode
)
throws
Exception
{
Cipher
ci
=
Cipher
.
getInstance
(
ALGO
+
"/"
+
MODE
+
"/"
+
PADDING
,
"SunJCE"
);
String
transformation
=
ALGO
+
"/"
+
mode
+
"/"
+
PADDING
;
Cipher
ci
=
Cipher
.
getInstance
(
transformation
,
"SunJCE"
);
// TEST FIX 4512524
KeyGenerator
kg
=
KeyGenerator
.
getInstance
(
ALGO
,
"SunJCE"
);
...
...
@@ -61,17 +61,14 @@ public class Test4512524 {
}
// passed all tests...hooray!
return
true
;
System
.
out
.
println
(
transformation
+
": Passed"
)
;
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
Security
.
addProvider
(
new
com
.
sun
.
crypto
.
provider
.
SunJCE
());
Test4512524
test
=
new
Test4512524
();
String
testName
=
test
.
getClass
().
getName
()
+
"["
+
ALGO
+
"/"
+
MODE
+
"/"
+
PADDING
+
"]"
;
if
(
test
.
execute
())
{
System
.
out
.
println
(
testName
+
": Passed!"
);
}
test
.
execute
(
"CBC"
);
test
.
execute
(
"GCM"
);
}
}
test/com/sun/crypto/provider/Cipher/AES/Test4512704.java
浏览文件 @
de5cc3f6
/*
* Copyright (c) 2002, 20
07
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 20
13
, 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
...
...
@@ -39,14 +39,14 @@ import com.sun.crypto.provider.*;
public
class
Test4512704
{
private
static
final
String
ALGO
=
"AES"
;
private
static
final
String
MODE
=
"CBC"
;
private
static
final
String
PADDING
=
"PKCS5Padding"
;
private
static
final
String
PADDING
=
"NoPadding"
;
private
static
final
int
KEYSIZE
=
16
;
// in bytes
public
boolean
execute
()
throws
Exception
{
AlgorithmParameterSpec
aps
=
null
;
public
void
execute
(
String
mode
)
throws
Exception
{
Cipher
ci
=
Cipher
.
getInstance
(
ALGO
+
"/"
+
MODE
+
"/"
+
PADDING
,
"SunJCE"
);
AlgorithmParameterSpec
aps
=
null
;
String
transformation
=
ALGO
+
"/"
+
mode
+
"/"
+
PADDING
;
Cipher
ci
=
Cipher
.
getInstance
(
transformation
,
"SunJCE"
);
KeyGenerator
kg
=
KeyGenerator
.
getInstance
(
ALGO
,
"SunJCE"
);
kg
.
init
(
KEYSIZE
*
8
);
...
...
@@ -57,19 +57,14 @@ public class Test4512704 {
}
catch
(
InvalidAlgorithmParameterException
ex
)
{
throw
new
Exception
(
"parameter should be generated when null is specified!"
);
}
// passed all tests...hooray!
return
true
;
System
.
out
.
println
(
transformation
+
": Passed"
);
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
Security
.
addProvider
(
new
com
.
sun
.
crypto
.
provider
.
SunJCE
());
Test4512704
test
=
new
Test4512704
();
String
testName
=
test
.
getClass
().
getName
()
+
"["
+
ALGO
+
"/"
+
MODE
+
"/"
+
PADDING
+
"]"
;
if
(
test
.
execute
())
{
System
.
out
.
println
(
testName
+
": Passed!"
);
}
test
.
execute
(
"CBC"
);
test
.
execute
(
"GCM"
);
}
}
test/com/sun/crypto/provider/Cipher/AES/Test4517355.java
浏览文件 @
de5cc3f6
/*
* Copyright (c) 2002, 20
07
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 20
13
, 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
...
...
@@ -41,16 +41,14 @@ import com.sun.crypto.provider.*;
public
class
Test4517355
{
private
static
final
String
ALGO
=
"AES"
;
private
static
final
String
MODE
=
"CBC"
;
private
static
final
String
PADDING
=
"PKCS5Padding"
;
private
static
final
int
KEYSIZE
=
16
;
// in bytes
p
ublic
boolean
execute
()
throws
Exception
{
Random
rdm
=
new
Random
();
byte
[]
plainText
=
new
byte
[
125
];
rdm
.
nextBytes
(
plainText
)
;
p
rivate
static
byte
[]
plainText
=
new
byte
[
125
];
public
void
execute
(
String
mode
,
String
padding
)
throws
Exception
{
String
transformation
=
ALGO
+
"/"
+
mode
+
"/"
+
padding
;
Cipher
ci
=
Cipher
.
getInstance
(
ALGO
+
"/"
+
MODE
+
"/"
+
PADDING
,
"SunJCE"
);
Cipher
ci
=
Cipher
.
getInstance
(
transformation
,
"SunJCE"
);
KeyGenerator
kg
=
KeyGenerator
.
getInstance
(
ALGO
,
"SunJCE"
);
kg
.
init
(
KEYSIZE
*
8
);
SecretKey
key
=
kg
.
generateKey
();
...
...
@@ -59,9 +57,14 @@ public class Test4517355 {
ci
.
init
(
Cipher
.
ENCRYPT_MODE
,
key
);
byte
[]
cipherText
=
ci
.
doFinal
(
plainText
);
byte
[]
iv
=
ci
.
getIV
();
AlgorithmParameterSpec
aps
=
new
IvParameterSpec
(
iv
);
ci
.
init
(
Cipher
.
DECRYPT_MODE
,
key
,
aps
);
if
(
mode
.
equalsIgnoreCase
(
"GCM"
))
{
AlgorithmParameters
params
=
ci
.
getParameters
();
ci
.
init
(
Cipher
.
DECRYPT_MODE
,
key
,
params
);
}
else
{
byte
[]
iv
=
ci
.
getIV
();
AlgorithmParameterSpec
aps
=
new
IvParameterSpec
(
iv
);
ci
.
init
(
Cipher
.
DECRYPT_MODE
,
key
,
aps
);
}
byte
[]
recoveredText
=
new
byte
[
plainText
.
length
];
try
{
int
len
=
ci
.
doFinal
(
cipherText
,
0
,
cipherText
.
length
,
...
...
@@ -80,21 +83,22 @@ public class Test4517355 {
throw
new
Exception
(
"encryption does not work!"
);
}
// 3. make sure padding is working
if
((
cipherText
.
length
/
16
)*
16
!=
cipherText
.
length
)
{
throw
new
Exception
(
"padding does not work!"
);
if
(
padding
.
equalsIgnoreCase
(
"PKCS5Padding"
))
{
if
((
cipherText
.
length
/
16
)*
16
!=
cipherText
.
length
)
{
throw
new
Exception
(
"padding does not work!"
);
}
}
// passed all tests...hooray!
return
true
;
System
.
out
.
println
(
transformation
+
": Passed"
);
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
Security
.
addProvider
(
new
com
.
sun
.
crypto
.
provider
.
SunJCE
());
Test4517355
test
=
new
Test4517355
();
String
testName
=
test
.
getClass
().
getName
()
+
"["
+
ALGO
+
"/"
+
MODE
+
"/"
+
PADDING
+
"]"
;
if
(
test
.
execute
())
{
System
.
out
.
println
(
testName
+
": Passed!
"
);
}
Random
rdm
=
new
Random
();
rdm
.
nextBytes
(
test
.
plainText
)
;
test
.
execute
(
"CBC"
,
"PKCS5Padding
"
);
test
.
execute
(
"GCM"
,
"NoPadding"
);
}
}
test/com/sun/crypto/provider/Cipher/AES/Test4626070.java
浏览文件 @
de5cc3f6
/*
* Copyright (c) 2002, 20
07
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 20
13
, 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
...
...
@@ -34,13 +34,11 @@ import java.util.*;
public
class
Test4626070
{
private
static
final
String
ALGO
=
"AES"
;
private
static
final
String
MODE
=
"CBC"
;
private
static
final
String
PADDING
=
"PKCS5Padding"
;
private
static
final
int
KEYSIZE
=
16
;
// in bytes
public
boolean
execute
(
)
throws
Exception
{
Cipher
ci
=
Cipher
.
getInstance
(
ALGO
+
"/"
+
MODE
+
"/"
+
PADDING
,
"SunJCE"
);
public
void
execute
(
String
mode
,
String
padding
)
throws
Exception
{
String
transformation
=
ALGO
+
"/"
+
mode
+
"/"
+
padding
;
Cipher
ci
=
Cipher
.
getInstance
(
transformation
,
"SunJCE"
);
KeyGenerator
kg
=
KeyGenerator
.
getInstance
(
ALGO
,
"SunJCE"
);
kg
.
init
(
KEYSIZE
*
8
);
SecretKey
key
=
kg
.
generateKey
();
...
...
@@ -58,18 +56,14 @@ public class Test4626070 {
throw
new
Exception
(
"key after wrap/unwrap is different from the original!"
);
}
// passed all tests...hooray!
return
true
;
System
.
out
.
println
(
transformation
+
": Passed"
);
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
Security
.
addProvider
(
new
com
.
sun
.
crypto
.
provider
.
SunJCE
());
Test4626070
test
=
new
Test4626070
();
String
testName
=
test
.
getClass
().
getName
()
+
"["
+
ALGO
+
"/"
+
MODE
+
"/"
+
PADDING
+
"]"
;
if
(
test
.
execute
())
{
System
.
out
.
println
(
testName
+
": Passed!"
);
}
test
.
execute
(
"CBC"
,
"PKCS5Padding"
);
test
.
execute
(
"GCM"
,
"NoPadding"
);
}
}
test/com/sun/crypto/provider/Cipher/AES/TestGCMKeyAndIvCheck.java
0 → 100644
浏览文件 @
de5cc3f6
/*
* Copyright (c) 2013, 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.
*
* 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.
*/
/*
* @test
* @bug 6996769
* @library ../UTIL
* @build TestUtil
* @run main TestGCMKeyAndIvCheck
* @summary Ensure that same key+iv can't be repeated used for encryption.
* @author Valerie Peng
*/
import
java.security.*
;
import
javax.crypto.*
;
import
javax.crypto.spec.*
;
import
java.math.*
;
import
com.sun.crypto.provider.*
;
import
java.util.*
;
public
class
TestGCMKeyAndIvCheck
{
private
static
final
byte
[]
AAD
=
new
byte
[
5
];
private
static
final
byte
[]
PT
=
new
byte
[
18
];
private
static
void
checkISE
(
Cipher
c
)
throws
Exception
{
// Subsequent encryptions should fail
try
{
c
.
updateAAD
(
AAD
);
throw
new
Exception
(
"Should throw ISE for updateAAD()"
);
}
catch
(
IllegalStateException
ise
)
{
// expected
}
try
{
c
.
update
(
PT
);
throw
new
Exception
(
"Should throw ISE for update()"
);
}
catch
(
IllegalStateException
ise
)
{
// expected
}
try
{
c
.
doFinal
(
PT
);
throw
new
Exception
(
"Should throw ISE for doFinal()"
);
}
catch
(
IllegalStateException
ise
)
{
// expected
}
}
public
void
test
()
throws
Exception
{
Cipher
c
=
Cipher
.
getInstance
(
"AES/GCM/NoPadding"
,
"SunJCE"
);
SecretKey
key
=
new
SecretKeySpec
(
new
byte
[
16
],
"AES"
);
// First try parameter-less init.
c
.
init
(
Cipher
.
ENCRYPT_MODE
,
key
);
c
.
updateAAD
(
AAD
);
byte
[]
ctPlusTag
=
c
.
doFinal
(
PT
);
// subsequent encryption should fail unless re-init w/ different key+iv
checkISE
(
c
);
// Validate the retrieved parameters against the IV and tag length.
AlgorithmParameters
params
=
c
.
getParameters
();
if
(
params
==
null
)
{
throw
new
Exception
(
"getParameters() should not return null"
);
}
GCMParameterSpec
spec
=
params
.
getParameterSpec
(
GCMParameterSpec
.
class
);
if
(
spec
.
getTLen
()
!=
(
ctPlusTag
.
length
-
PT
.
length
)*
8
)
{
throw
new
Exception
(
"Parameters contains incorrect TLen value"
);
}
if
(!
Arrays
.
equals
(
spec
.
getIV
(),
c
.
getIV
()))
{
throw
new
Exception
(
"Parameters contains incorrect IV value"
);
}
// Should be ok to use the same key+iv for decryption
c
.
init
(
Cipher
.
DECRYPT_MODE
,
key
,
params
);
c
.
updateAAD
(
AAD
);
byte
[]
recovered
=
c
.
doFinal
(
ctPlusTag
);
if
(!
Arrays
.
equals
(
recovered
,
PT
))
{
throw
new
Exception
(
"decryption result mismatch"
);
}
// Now try to encrypt again using the same key+iv; should fail also
try
{
c
.
init
(
Cipher
.
ENCRYPT_MODE
,
key
,
params
);
throw
new
Exception
(
"Should throw exception when same key+iv is used"
);
}
catch
(
InvalidAlgorithmParameterException
iape
)
{
// expected
}
// Now try to encrypt again using parameter-less init; should work
c
.
init
(
Cipher
.
ENCRYPT_MODE
,
key
);
c
.
doFinal
(
PT
);
// make sure a different iv is used
byte
[]
iv
=
c
.
getIV
();
if
(
Arrays
.
equals
(
spec
.
getIV
(),
iv
))
{
throw
new
Exception
(
"IV should be different now"
);
}
// Now try to encrypt again using a different parameter; should work
c
.
init
(
Cipher
.
ENCRYPT_MODE
,
key
,
new
GCMParameterSpec
(
128
,
new
byte
[
30
]));
c
.
updateAAD
(
AAD
);
c
.
doFinal
(
PT
);
// subsequent encryption should fail unless re-init w/ different key+iv
checkISE
(
c
);
// Now try decryption twice in a row; no re-init required and
// same parameters is used.
c
.
init
(
Cipher
.
DECRYPT_MODE
,
key
,
params
);
c
.
updateAAD
(
AAD
);
recovered
=
c
.
doFinal
(
ctPlusTag
);
c
.
updateAAD
(
AAD
);
recovered
=
c
.
doFinal
(
ctPlusTag
);
if
(!
Arrays
.
equals
(
recovered
,
PT
))
{
throw
new
Exception
(
"decryption result mismatch"
);
}
// Now try decryption again and re-init using the same parameters
c
.
init
(
Cipher
.
DECRYPT_MODE
,
key
,
params
);
c
.
updateAAD
(
AAD
);
recovered
=
c
.
doFinal
(
ctPlusTag
);
// init to decrypt w/o parameters; should fail with IKE as
// javadoc specified
try
{
c
.
init
(
Cipher
.
DECRYPT_MODE
,
key
);
throw
new
Exception
(
"Should throw IKE for dec w/o params"
);
}
catch
(
InvalidKeyException
ike
)
{
// expected
}
// Lastly, try encryption AND decryption w/ wrong type of parameters,
// e.g. IvParameterSpec
try
{
c
.
init
(
Cipher
.
ENCRYPT_MODE
,
key
,
new
IvParameterSpec
(
iv
));
throw
new
Exception
(
"Should throw IAPE"
);
}
catch
(
InvalidAlgorithmParameterException
iape
)
{
// expected
}
try
{
c
.
init
(
Cipher
.
DECRYPT_MODE
,
key
,
new
IvParameterSpec
(
iv
));
throw
new
Exception
(
"Should throw IAPE"
);
}
catch
(
InvalidAlgorithmParameterException
iape
)
{
// expected
}
System
.
out
.
println
(
"Test Passed!"
);
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
TestGCMKeyAndIvCheck
t
=
new
TestGCMKeyAndIvCheck
();
t
.
test
();
}
}
test/com/sun/crypto/provider/Cipher/AES/TestKATForGCM.java
0 → 100644
浏览文件 @
de5cc3f6
/*
* Copyright (c) 2013, 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.
*
* 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.
*/
/*
* @test
* @bug 6996769
* @library ../UTIL
* @build TestUtil
* @run main TestKATForGCM
* @summary Known Answer Test for AES cipher with GCM mode support in
* SunJCE provider.
* @author Valerie Peng
*/
import
java.security.*
;
import
javax.crypto.*
;
import
javax.crypto.spec.*
;
import
java.math.*
;
import
com.sun.crypto.provider.*
;
import
java.util.*
;
public
class
TestKATForGCM
{
// Utility methods
private
static
byte
[]
HexToBytes
(
String
hexVal
)
{
if
(
hexVal
==
null
)
return
new
byte
[
0
];
byte
[]
result
=
new
byte
[
hexVal
.
length
()/
2
];
for
(
int
i
=
0
;
i
<
result
.
length
;
i
++)
{
// 2 characters at a time
String
byteVal
=
hexVal
.
substring
(
2
*
i
,
2
*
i
+
2
);
result
[
i
]
=
Integer
.
valueOf
(
byteVal
,
16
).
byteValue
();
}
return
result
;
}
private
static
class
TestVector
{
SecretKey
key
;
byte
[]
plainText
;
byte
[]
aad
;
byte
[]
cipherText
;
byte
[]
tag
;
GCMParameterSpec
spec
;
String
info
;
TestVector
(
String
key
,
String
iv
,
String
pt
,
String
aad
,
String
ct
,
String
tag
)
{
this
.
key
=
new
SecretKeySpec
(
HexToBytes
(
key
),
"AES"
);
this
.
plainText
=
HexToBytes
(
pt
);
this
.
aad
=
HexToBytes
(
aad
);
this
.
cipherText
=
HexToBytes
(
ct
);
this
.
tag
=
HexToBytes
(
tag
);
this
.
spec
=
new
GCMParameterSpec
(
this
.
tag
.
length
*
8
,
HexToBytes
(
iv
));
this
.
info
=
"key="
+
key
+
", iv="
+
iv
+
", pt="
+
pt
+
",aad="
+
aad
+
", ct="
+
ct
+
", tag="
+
tag
;
}
public
String
toString
()
{
return
info
;
}
}
// These test vectors are found off NIST's CAVP page
// http://csrc.nist.gov/groups/STM/cavp/index.html
// inside the link named "GCM Test Vectors", i.e.
// http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
// CAVS 14.0, set of test vectors w/ count = 0, keysize = 128
private
static
TestVector
[]
testValues
=
{
// 96-bit iv w/ 128/120/112/104/96-bit tags
// no plain text, no aad
new
TestVector
(
"11754cd72aec309bf52f7687212e8957"
,
"3c819d9a9bed087615030b65"
,
null
,
null
,
null
,
"250327c674aaf477aef2675748cf6971"
),
new
TestVector
(
"272f16edb81a7abbea887357a58c1917"
,
"794ec588176c703d3d2a7a07"
,
null
,
null
,
null
,
"b6e6f197168f5049aeda32dafbdaeb"
),
new
TestVector
(
"81b6844aab6a568c4556a2eb7eae752f"
,
"ce600f59618315a6829bef4d"
,
null
,
null
,
null
,
"89b43e9dbc1b4f597dbbc7655bb5"
),
new
TestVector
(
"cde2f9a9b1a004165ef9dc981f18651b"
,
"29512c29566c7322e1e33e8e"
,
null
,
null
,
null
,
"2e58ce7dabd107c82759c66a75"
),
new
TestVector
(
"b01e45cc3088aaba9fa43d81d481823f"
,
"5a2c4a66468713456a4bd5e1"
,
null
,
null
,
null
,
"014280f944f53c681164b2ff"
),
// 96-bit iv w/ 128/120/112/104/96-bit tags
// no plain text, 16-byte aad
new
TestVector
(
"77be63708971c4e240d1cb79e8d77feb"
,
"e0e00f19fed7ba0136a797f3"
,
null
,
"7a43ec1d9c0a5a78a0b16533a6213cab"
,
null
,
"209fcc8d3675ed938e9c7166709dd946"
),
new
TestVector
(
"da0b615656135194ba6d3c851099bc48"
,
"d39d4b4d3cc927885090e6c3"
,
null
,
"e7e5e6f8dac913036cb2ff29e8625e0e"
,
null
,
"ab967711a5770461724460b07237e2"
),
new
TestVector
(
"7e0986937a88eef894235aba4a2f43b2"
,
"92c4a631695907166b422d60"
,
null
,
"85c185f8518f9f2cd597a8f9208fc76b"
,
null
,
"3bb916b728df94fe9d1916736be1"
),
new
TestVector
(
"c3db570d7f0c21e86b028f11465d1dc9"
,
"f86970f58ceef89fc7cb679e"
,
null
,
"c095240708c0f57c288d86090ae34ee1"
,
null
,
"e043c52160d652e82c7262fcf4"
),
new
TestVector
(
"bea48ae4980d27f357611014d4486625"
,
"32bddb5c3aa998a08556454c"
,
null
,
"8a50b0b8c7654bced884f7f3afda2ead"
,
null
,
"8e0f6d8bf05ffebe6f500eb1"
),
// 96-bit iv w/ 128/120/112/104/96-bit tags
// no plain text, 20-byte aad
new
TestVector
(
"2fb45e5b8f993a2bfebc4b15b533e0b4"
,
"5b05755f984d2b90f94b8027"
,
null
,
"e85491b2202caf1d7dce03b97e09331c32473941"
,
null
,
"c75b7832b2a2d9bd827412b6ef5769db"
),
new
TestVector
(
"9bf406339fcef9675bbcf156aa1a0661"
,
"8be4a9543d40f542abacac95"
,
null
,
"7167cbf56971793186333a6685bbd58d47d379b3"
,
null
,
"5e7968d7bbd5ba58cfcc750e2ef8f1"
),
new
TestVector
(
"a2e962fff70fd0f4d63be728b80556fc"
,
"1fa7103483de43d09bc23db4"
,
null
,
"2a58edf1d53f46e4e7ee5e77ee7aeb60fc360658"
,
null
,
"fa37f2dbbefab1451eae1d0d74ca"
),
new
TestVector
(
"6bf4fdce82926dcdfc52616ed5f23695"
,
"cc0f5899a10615567e1193ed"
,
null
,
"3340655592374c1da2f05aac3ee111014986107f"
,
null
,
"8ad3385cce3b5e7c985908192c"
),
new
TestVector
(
"4df7a13e43c3d7b66b1a72fac5ba398e"
,
"97179a3a2d417908dcf0fb28"
,
null
,
"cbb7fc0010c255661e23b07dbd804b1e06ae70ac"
,
null
,
"37791edae6c137ea946cfb40"
),
// 96-bit iv w/ 128-bit tags, 13/16/32/51-byte plain text, no aad
new
TestVector
(
"fe9bb47deb3a61e423c2231841cfd1fb"
,
"4d328eb776f500a2f7fb47aa"
,
"f1cc3818e421876bb6b8bbd6c9"
,
null
,
"b88c5c1977b35b517b0aeae967"
,
"43fd4727fe5cdb4b5b42818dea7ef8c9"
),
new
TestVector
(
"7fddb57453c241d03efbed3ac44e371c"
,
"ee283a3fc75575e33efd4887"
,
"d5de42b461646c255c87bd2962d3b9a2"
,
null
,
"2ccda4a5415cb91e135c2a0f78c9b2fd"
,
"b36d1df9b9d5e596f83e8b7f52971cb3"
),
new
TestVector
(
"9971071059abc009e4f2bd69869db338"
,
"07a9a95ea3821e9c13c63251"
,
"f54bc3501fed4f6f6dfb5ea80106df0bd836e6826225b75c0222f6e859b35983"
,
null
,
"0556c159f84ef36cb1602b4526b12009c775611bffb64dc0d9ca9297cd2c6a01"
,
"7870d9117f54811a346970f1de090c41"
),
new
TestVector
(
"594157ec4693202b030f33798b07176d"
,
"49b12054082660803a1df3df"
,
"3feef98a976a1bd634f364ac428bb59cd51fb159ec1789946918dbd50ea6c9d594a3a31a5269b0da6936c29d063a5fa2cc8a1c"
,
null
,
"c1b7a46a335f23d65b8db4008a49796906e225474f4fe7d39e55bf2efd97fd82d4167de082ae30fa01e465a601235d8d68bc69"
,
"ba92d3661ce8b04687e8788d55417dc2"
),
// 96-bit iv w/ 128-bit tags, 16-byte plain text, 16/20/48/90-byte aad
new
TestVector
(
"c939cc13397c1d37de6ae0e1cb7c423c"
,
"b3d8cc017cbb89b39e0f67e2"
,
"c3b3c41f113a31b73d9a5cd432103069"
,
"24825602bd12a984e0092d3e448eda5f"
,
"93fe7d9e9bfd10348a5606e5cafa7354"
,
"0032a1dc85f1c9786925a2e71d8272dd"
),
new
TestVector
(
"d4a22488f8dd1d5c6c19a7d6ca17964c"
,
"f3d5837f22ac1a0425e0d1d5"
,
"7b43016a16896497fb457be6d2a54122"
,
"f1c5d424b83f96c6ad8cb28ca0d20e475e023b5a"
,
"c2bd67eef5e95cac27e3b06e3031d0a8"
,
"f23eacf9d1cdf8737726c58648826e9c"
),
new
TestVector
(
"89850dd398e1f1e28443a33d40162664"
,
"e462c58482fe8264aeeb7231"
,
"2805cdefb3ef6cc35cd1f169f98da81a"
,
"d74e99d1bdaa712864eec422ac507bddbe2b0d4633cd3dff29ce5059b49fe868526c59a2a3a604457bc2afea866e7606"
,
"ba80e244b7fc9025cd031d0f63677e06"
,
"d84a8c3eac57d1bb0e890a8f461d1065"
),
new
TestVector
(
"bd7c5c63b7542b56a00ebe71336a1588"
,
"87721f23ba9c3c8ea5571abc"
,
"de15ddbb1e202161e8a79af6a55ac6f3"
,
"a6ec8075a0d3370eb7598918f3b93e48444751624997b899a87fa6a9939f844e008aa8b70e9f4c3b1a19d3286bf543e7127bfecba1ad17a5ec53fccc26faecacc4c75369498eaa7d706aef634d0009279b11e4ba6c993e5e9ed9"
,
"41eb28c0fee4d762de972361c863bc80"
,
"9cb567220d0b252eb97bff46e4b00ff8"
),
// 8/1024-bit iv w/ 128-bit tag, no plain text, no aad
new
TestVector
(
"1672c3537afa82004c6b8a46f6f0d026"
,
"05"
,
null
,
null
,
null
,
"8e2ad721f9455f74d8b53d3141f27e8e"
),
new
TestVector
(
"d0f1f4defa1e8c08b4b26d576392027c"
,
"42b4f01eb9f5a1ea5b1eb73b0fb0baed54f387ecaa0393c7d7dffc6af50146ecc021abf7eb9038d4303d91f8d741a11743166c0860208bcc02c6258fd9511a2fa626f96d60b72fcff773af4e88e7a923506e4916ecbd814651e9f445adef4ad6a6b6c7290cc13b956130eef5b837c939fcac0cbbcc9656cd75b13823ee5acdac"
,
null
,
null
,
null
,
"7ab49b57ddf5f62c427950111c5c4f0d"
),
// 8-bit iv w/ 128-bit tag, 13-byte plain text, 90-byte aad
new
TestVector
(
"9f79239f0904eace50784b863e723f6b"
,
"d9"
,
"bdb0bb10c87965acd34d146171"
,
"44db436089327726c5f01139e1f339735c9e85514ccc2f167bad728010fb34a9072a9794c8a5e7361b1d0dbcdc9ac4091e354bb2896561f0486645252e9c78c86beece91bfa4f7cc4a8794ce1f305b1b735efdbf1ed1563c0be0"
,
"7e5a7c8dadb3f0c7335b4d9d8d"
,
"6b6ef1f53723a89f3bb7c6d043840717"
),
// 1024-bit iv w/ 128-bit tag, 51-byte plain text, 48-byte aad
new
TestVector
(
"141f1ce91989b07e7eb6ae1dbd81ea5e"
,
"49451da24bd6074509d3cebc2c0394c972e6934b45a1d91f3ce1d3ca69e194aa1958a7c21b6f21d530ce6d2cc5256a3f846b6f9d2f38df0102c4791e57df038f6e69085646007df999751e248e06c47245f4cd3b8004585a7470dee1690e9d2d63169a58d243c0b57b3e5b4a481a3e4e8c60007094ef3adea2e8f05dd3a1396f"
,
"d384305af2388699aa302f510913fed0f2cb63ba42efa8c5c9de2922a2ec2fe87719dadf1eb0aef212b51e74c9c5b934104a43"
,
"630cf18a91cc5a6481ac9eefd65c24b1a3c93396bd7294d6b8ba323951727666c947a21894a079ef061ee159c05beeb4"
,
"f4c34e5fbe74c0297313268296cd561d59ccc95bbfcdfcdc71b0097dbd83240446b28dc088abd42b0fc687f208190ff24c0548"
,
"dbb93bbb56d0439cd09f620a57687f5d"
),
};
public
boolean
execute
(
TestVector
[]
testValues
)
throws
Exception
{
boolean
testFailed
=
false
;
Cipher
c
=
Cipher
.
getInstance
(
"AES/GCM/NoPadding"
,
"SunJCE"
);
for
(
int
i
=
0
;
i
<
testValues
.
length
;
i
++)
{
try
{
c
.
init
(
Cipher
.
ENCRYPT_MODE
,
testValues
[
i
].
key
,
testValues
[
i
].
spec
);
c
.
updateAAD
(
testValues
[
i
].
aad
);
byte
[]
ctPlusTag
=
c
.
doFinal
(
testValues
[
i
].
plainText
);
c
.
init
(
Cipher
.
DECRYPT_MODE
,
testValues
[
i
].
key
,
testValues
[
i
].
spec
);
c
.
updateAAD
(
testValues
[
i
].
aad
);
byte
[]
pt
=
c
.
doFinal
(
ctPlusTag
);
// should fail if tag mismatched
// check encryption/decryption results just to be sure
if
(!
Arrays
.
equals
(
testValues
[
i
].
plainText
,
pt
))
{
System
.
out
.
println
(
"PlainText diff failed for test# "
+
i
);
testFailed
=
true
;
}
int
ctLen
=
testValues
[
i
].
cipherText
.
length
;
if
(!
Arrays
.
equals
(
testValues
[
i
].
cipherText
,
Arrays
.
copyOf
(
ctPlusTag
,
ctLen
)))
{
System
.
out
.
println
(
"CipherText diff failed for test# "
+
i
);
testFailed
=
true
;
}
int
tagLen
=
testValues
[
i
].
tag
.
length
;
if
(!
Arrays
.
equals
(
testValues
[
i
].
tag
,
Arrays
.
copyOfRange
(
ctPlusTag
,
ctLen
,
ctLen
+
tagLen
)))
{
System
.
out
.
println
(
"Tag diff failed for test# "
+
i
);
testFailed
=
true
;
}
}
catch
(
Exception
ex
)
{
// continue testing other test vectors
System
.
out
.
println
(
"Failed Test Vector: "
+
testValues
[
i
]);
ex
.
printStackTrace
();
testFailed
=
true
;
continue
;
}
}
if
(
testFailed
)
{
throw
new
Exception
(
"Test Failed"
);
}
// passed all tests...hooray!
return
true
;
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
TestKATForGCM
test
=
new
TestKATForGCM
();
if
(
test
.
execute
(
testValues
))
{
System
.
out
.
println
(
"Test Passed!"
);
}
}
}
test/javax/crypto/Cipher/GCMAPI.java
浏览文件 @
de5cc3f6
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011,
2013,
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
...
...
@@ -78,6 +78,8 @@ public class GCMAPI {
c
.
updateAAD
(
src
);
}
catch
(
UnsupportedOperationException
e
)
{
// swallow
}
catch
(
IllegalStateException
ise
)
{
// swallow
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
failed
++;
...
...
@@ -99,6 +101,8 @@ public class GCMAPI {
c
.
updateAAD
(
src
,
offset
,
len
);
}
catch
(
UnsupportedOperationException
e
)
{
// swallow
}
catch
(
IllegalStateException
ise
)
{
// swallow
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
failed
++;
...
...
@@ -120,6 +124,8 @@ public class GCMAPI {
c
.
updateAAD
(
src
);
}
catch
(
UnsupportedOperationException
e
)
{
// swallow
}
catch
(
IllegalStateException
ise
)
{
// swallow
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
failed
++;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录