1 Star 0 Fork 81

Alex Gao/openjdk-1.8.0

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
8014628-Support-AES-Encryption-with-HMAC-SHA2-for-Ke.patch 92.23 KB
一键复制 编辑 原始数据 按行查看 历史
佛系少年中二 提交于 2024-07-19 15:08 . update to jdk8u422
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214
From 1f3126944b08e62bd79bb1624319f934654d933c Mon Sep 17 00:00:00 2001
Date: Thu, 27 Jul 2023 11:48:47 +0800
Subject: [PATCH] [Backport]8014628: Support AES Encryption with HMAC-SHA2 for Kerberos 5
---
.../javax/security/auth/kerberos/KeyImpl.java | 8 +-
.../sun/security/jgss/krb5/CipherHelper.java | 204 +++++++
.../classes/sun/security/krb5/Checksum.java | 4 +
.../classes/sun/security/krb5/Config.java | 16 +-
.../sun/security/krb5/EncryptedData.java | 8 +-
.../sun/security/krb5/EncryptionKey.java | 17 +-
.../crypto/Aes128CtsHmacSha2EType.java | 112 ++++
.../krb5/internal/crypto/Aes128Sha2.java | 83 +++
.../crypto/Aes256CtsHmacSha2EType.java | 112 ++++
.../krb5/internal/crypto/Aes256Sha2.java | 86 +++
.../krb5/internal/crypto/CksumType.java | 12 +
.../security/krb5/internal/crypto/EType.java | 44 +-
.../crypto/HmacSha2Aes128CksumType.java | 106 ++++
.../crypto/HmacSha2Aes256CksumType.java | 106 ++++
.../internal/crypto/dk/AesSha2DkCrypto.java | 541 ++++++++++++++++++
.../krb5/internal/crypto/dk/DkCrypto.java | 6 +-
.../sun/security/krb5/auto/BasicKrb5Test.java | 30 +-
jdk/test/sun/security/krb5/auto/KDC.java | 42 +-
.../krb5/auto/ReplayCacheTestProc.java | 11 +-
.../sun/security/krb5/etype/ETypeOrder.java | 4 +-
.../security/krb5/etype/KerberosAesSha2.java | 209 +++++++
21 files changed, 1704 insertions(+), 57 deletions(-)
create mode 100644 jdk/src/share/classes/sun/security/krb5/internal/crypto/Aes128CtsHmacSha2EType.java
create mode 100644 jdk/src/share/classes/sun/security/krb5/internal/crypto/Aes128Sha2.java
create mode 100644 jdk/src/share/classes/sun/security/krb5/internal/crypto/Aes256CtsHmacSha2EType.java
create mode 100644 jdk/src/share/classes/sun/security/krb5/internal/crypto/Aes256Sha2.java
create mode 100644 jdk/src/share/classes/sun/security/krb5/internal/crypto/HmacSha2Aes128CksumType.java
create mode 100644 jdk/src/share/classes/sun/security/krb5/internal/crypto/HmacSha2Aes256CksumType.java
create mode 100644 jdk/src/share/classes/sun/security/krb5/internal/crypto/dk/AesSha2DkCrypto.java
create mode 100644 jdk/test/sun/security/krb5/etype/KerberosAesSha2.java
diff --git a/jdk/src/share/classes/javax/security/auth/kerberos/KeyImpl.java b/jdk/src/share/classes/javax/security/auth/kerberos/KeyImpl.java
index 9d36d1e9e..571387e0c 100644
--- a/jdk/src/share/classes/javax/security/auth/kerberos/KeyImpl.java
+++ b/jdk/src/share/classes/javax/security/auth/kerberos/KeyImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -138,6 +138,12 @@ class KeyImpl implements SecretKey, Destroyable, Serializable {
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
return "aes256-cts-hmac-sha1-96";
+ case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128:
+ return "aes128-cts-hmac-sha256-128";
+
+ case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA384_192:
+ return "aes256-cts-hmac-sha384-192";
+
case EncryptedData.ETYPE_NULL:
return "none";
diff --git a/jdk/src/share/classes/sun/security/jgss/krb5/CipherHelper.java b/jdk/src/share/classes/sun/security/jgss/krb5/CipherHelper.java
index 0b8adfb61..2eac76256 100644
--- a/jdk/src/share/classes/sun/security/jgss/krb5/CipherHelper.java
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/CipherHelper.java
@@ -40,6 +40,8 @@ import java.security.MessageDigest;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import sun.security.krb5.*;
+import sun.security.krb5.internal.crypto.Aes128Sha2;
+import sun.security.krb5.internal.crypto.Aes256Sha2;
import sun.security.krb5.internal.crypto.Des3;
import sun.security.krb5.internal.crypto.Aes128;
import sun.security.krb5.internal.crypto.Aes256;
@@ -101,6 +103,8 @@ class CipherHelper {
case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
+ case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128:
+ case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA384_192:
sgnAlg = -1;
sealAlg = -1;
break;
@@ -365,6 +369,33 @@ class CipherHelper {
throw ge;
}
+ case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128:
+ try {
+ byte[] answer = Aes128Sha2.calculateChecksum(keybytes, key_usage,
+ buf, 0, total);
+ return answer;
+ } catch (GeneralSecurityException e) {
+ GSSException ge = new GSSException(GSSException.FAILURE, -1,
+ "Could not use AES128 signing algorithm - " +
+ e.getMessage());
+ ge.initCause(e);
+ throw ge;
+ }
+
+ case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA384_192:
+ try {
+ byte[] answer = Aes256Sha2.calculateChecksum(keybytes, key_usage,
+ buf, 0, total);
+ return answer;
+ } catch (GeneralSecurityException e) {
+ GSSException ge = new GSSException(GSSException.FAILURE, -1,
+ "Could not use AES256 signing algorithm - " +
+ e.getMessage());
+ ge.initCause(e);
+ throw ge;
+ }
+
+
default:
throw new GSSException(GSSException.FAILURE, -1,
"Unsupported encryption type: " + etype);
@@ -517,6 +548,11 @@ class CipherHelper {
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
return Aes256.getChecksumLength();
+ case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128:
+ return Aes128Sha2.getChecksumLength();
+ case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA384_192:
+ return Aes256Sha2.getChecksumLength();
+
case EncryptedData.ETYPE_ARCFOUR_HMAC:
// only first 8 octets of HMAC Sgn_Cksum are used
return HMAC_CHECKSUM_SIZE;
@@ -574,6 +610,14 @@ class CipherHelper {
aes256Decrypt(token, ciphertext, cStart, cLen,
plaintext, pStart, key_usage);
break;
+ case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128:
+ aes128Sha2Decrypt(token, ciphertext, cStart, cLen,
+ plaintext, pStart, key_usage);
+ break;
+ case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA384_192:
+ aes256Sha2Decrypt(token, ciphertext, cStart, cLen,
+ plaintext, pStart, key_usage);
+ break;
default:
throw new GSSException(GSSException.FAILURE, -1,
"Unsupported etype: " + etype);
@@ -654,6 +698,14 @@ class CipherHelper {
aes256Decrypt(token, ciphertext, 0, cLen,
plaintext, pStart, key_usage);
break;
+ case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128:
+ aes128Sha2Decrypt(token, ciphertext, 0, cLen,
+ plaintext, pStart, key_usage);
+ break;
+ case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA384_192:
+ aes256Sha2Decrypt(token, ciphertext, 0, cLen,
+ plaintext, pStart, key_usage);
+ break;
default:
throw new GSSException(GSSException.FAILURE, -1,
"Unsupported etype: " + etype);
@@ -720,6 +772,12 @@ class CipherHelper {
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
return aes256Encrypt(confounder, tokenHeader,
plaintext, start, len, key_usage);
+ case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128:
+ return aes128Sha2Encrypt(confounder, tokenHeader,
+ plaintext, start, len, key_usage);
+ case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA384_192:
+ return aes256Sha2Encrypt(confounder, tokenHeader,
+ plaintext, start, len, key_usage);
default:
throw new GSSException(GSSException.FAILURE, -1,
"Unsupported etype: " + etype);
@@ -796,6 +854,14 @@ class CipherHelper {
ctext = aes256Encrypt(confounder, tokenHeader,
plaintext, pStart, pLen, key_usage);
break;
+ case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128:
+ ctext = aes128Sha2Encrypt(confounder, tokenHeader,
+ plaintext, pStart, pLen, key_usage);
+ break;
+ case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA384_192:
+ ctext = aes256Sha2Encrypt(confounder, tokenHeader,
+ plaintext, pStart, pLen, key_usage);
+ break;
default:
throw new GSSException(GSSException.FAILURE, -1,
"Unsupported etype: " + etype);
@@ -1317,6 +1383,38 @@ class CipherHelper {
}
}
+ private byte[] aes128Sha2Encrypt(byte[] confounder, byte[] tokenHeader,
+ byte[] plaintext, int start, int len, int key_usage)
+ throws GSSException {
+
+ // encrypt { AES-plaintext-data | filler | header }
+ // AES-plaintext-data { confounder | plaintext }
+ // WrapToken = { tokenHeader |
+ // Encrypt (confounder | plaintext | tokenHeader ) | HMAC }
+
+ byte[] all = new byte[confounder.length + len + tokenHeader.length];
+ System.arraycopy(confounder, 0, all, 0, confounder.length);
+ System.arraycopy(plaintext, start, all, confounder.length, len);
+ System.arraycopy(tokenHeader, 0, all, confounder.length+len,
+ tokenHeader.length);
+
+ // Krb5Token.debug("\naes128Sha2Encrypt:" + Krb5Token.getHexBytes(all));
+ try {
+ byte[] answer = Aes128Sha2.encryptRaw(keybytes, key_usage,
+ ZERO_IV_AES,
+ all, 0, all.length);
+ // Krb5Token.debug("\naes128Sha2Encrypt encrypted:" +
+ // Krb5Token.getHexBytes(answer));
+ return answer;
+ } catch (Exception e) {
+ // GeneralSecurityException, KrbCryptoException
+ GSSException ge = new GSSException(GSSException.FAILURE, -1,
+ "Could not use Aes128Sha2 Cipher - " + e.getMessage());
+ ge.initCause(e);
+ throw ge;
+ }
+ }
+
private void aes128Decrypt(WrapToken_v2 token, byte[] ciphertext,
int cStart, int cLen, byte[] plaintext, int pStart, int key_usage)
throws GSSException {
@@ -1354,6 +1452,43 @@ class CipherHelper {
*/
}
+ private void aes128Sha2Decrypt(WrapToken_v2 token, byte[] ciphertext,
+ int cStart, int cLen, byte[] plaintext, int pStart, int key_usage)
+ throws GSSException {
+
+ byte[] ptext = null;
+
+ try {
+ ptext = Aes128Sha2.decryptRaw(keybytes, key_usage,
+ ZERO_IV_AES, ciphertext, cStart, cLen);
+ } catch (GeneralSecurityException e) {
+ GSSException ge = new GSSException(GSSException.FAILURE, -1,
+ "Could not use AES128Sha2 Cipher - " + e.getMessage());
+ ge.initCause(e);
+ throw ge;
+ }
+
+ /*
+ Krb5Token.debug("\naes128Sha2Decrypt in: " +
+ Krb5Token.getHexBytes(ciphertext, cStart, cLen));
+ Krb5Token.debug("\naes128Sha2Decrypt plain: " +
+ Krb5Token.getHexBytes(ptext));
+ Krb5Token.debug("\naes128Sha2Decrypt ptext: " +
+ Krb5Token.getHexBytes(ptext));
+ */
+
+ // Strip out confounder and token header
+ int len = ptext.length - WrapToken_v2.CONFOUNDER_SIZE -
+ WrapToken_v2.TOKEN_HEADER_SIZE;
+ System.arraycopy(ptext, WrapToken_v2.CONFOUNDER_SIZE,
+ plaintext, pStart, len);
+
+ /*
+ Krb5Token.debug("\naes128Sha2Decrypt plaintext: " +
+ Krb5Token.getHexBytes(plaintext, pStart, len));
+ */
+ }
+
private byte[] aes256Encrypt(byte[] confounder, byte[] tokenHeader,
byte[] plaintext, int start, int len, int key_usage)
throws GSSException {
@@ -1386,6 +1521,38 @@ class CipherHelper {
}
}
+ private byte[] aes256Sha2Encrypt(byte[] confounder, byte[] tokenHeader,
+ byte[] plaintext, int start, int len, int key_usage)
+ throws GSSException {
+
+ // encrypt { AES-plaintext-data | filler | header }
+ // AES-plaintext-data { confounder | plaintext }
+ // WrapToken = { tokenHeader |
+ // Encrypt (confounder | plaintext | tokenHeader ) | HMAC }
+
+ byte[] all = new byte[confounder.length + len + tokenHeader.length];
+ System.arraycopy(confounder, 0, all, 0, confounder.length);
+ System.arraycopy(plaintext, start, all, confounder.length, len);
+ System.arraycopy(tokenHeader, 0, all, confounder.length+len,
+ tokenHeader.length);
+
+ // Krb5Token.debug("\naes256Sha2Encrypt:" + Krb5Token.getHexBytes(all));
+
+ try {
+ byte[] answer = Aes256Sha2.encryptRaw(keybytes, key_usage,
+ ZERO_IV_AES, all, 0, all.length);
+ // Krb5Token.debug("\naes256Sha2Encrypt encrypted:" +
+ // Krb5Token.getHexBytes(answer));
+ return answer;
+ } catch (Exception e) {
+ // GeneralSecurityException, KrbCryptoException
+ GSSException ge = new GSSException(GSSException.FAILURE, -1,
+ "Could not use Aes256Sha2 Cipher - " + e.getMessage());
+ ge.initCause(e);
+ throw ge;
+ }
+ }
+
private void aes256Decrypt(WrapToken_v2 token, byte[] ciphertext,
int cStart, int cLen, byte[] plaintext, int pStart, int key_usage)
throws GSSException {
@@ -1423,6 +1590,43 @@ class CipherHelper {
}
+ private void aes256Sha2Decrypt(WrapToken_v2 token, byte[] ciphertext,
+ int cStart, int cLen, byte[] plaintext, int pStart, int key_usage)
+ throws GSSException {
+
+ byte[] ptext;
+ try {
+ ptext = Aes256Sha2.decryptRaw(keybytes, key_usage,
+ ZERO_IV_AES, ciphertext, cStart, cLen);
+ } catch (GeneralSecurityException e) {
+ GSSException ge = new GSSException(GSSException.FAILURE, -1,
+ "Could not use AES256Sha2 Cipher - " + e.getMessage());
+ ge.initCause(e);
+ throw ge;
+ }
+
+ /*
+ Krb5Token.debug("\naes256Sha2Decrypt in: " +
+ Krb5Token.getHexBytes(ciphertext, cStart, cLen));
+ Krb5Token.debug("\naes256Sha2Decrypt plain: " +
+ Krb5Token.getHexBytes(ptext));
+ Krb5Token.debug("\naes256Sha2Decrypt ptext: " +
+ Krb5Token.getHexBytes(ptext));
+ */
+
+ // Strip out confounder and token header
+ int len = ptext.length - WrapToken_v2.CONFOUNDER_SIZE -
+ WrapToken_v2.TOKEN_HEADER_SIZE;
+ System.arraycopy(ptext, WrapToken_v2.CONFOUNDER_SIZE,
+ plaintext, pStart, len);
+
+ /*
+ Krb5Token.debug("\naes256Sha2Decrypt plaintext: " +
+ Krb5Token.getHexBytes(plaintext, pStart, len));
+ */
+
+ }
+
/**
* This class provides a truncated inputstream needed by WrapToken. The
* truncated inputstream is passed to CipherInputStream. It prevents
diff --git a/jdk/src/share/classes/sun/security/krb5/Checksum.java b/jdk/src/share/classes/sun/security/krb5/Checksum.java
index 3f89f97cd..61ed36397 100644
--- a/jdk/src/share/classes/sun/security/krb5/Checksum.java
+++ b/jdk/src/share/classes/sun/security/krb5/Checksum.java
@@ -66,6 +66,10 @@ public class Checksum {
public static final int CKSUMTYPE_HMAC_SHA1_96_AES128 = 15; // 96
public static final int CKSUMTYPE_HMAC_SHA1_96_AES256 = 16; // 96
+ // rfc8009
+ public static final int CKSUMTYPE_HMAC_SHA256_128_AES128 = 19; // 96
+ public static final int CKSUMTYPE_HMAC_SHA384_192_AES256 = 20; // 96
+
// draft-brezak-win2k-krb-rc4-hmac-04.txt
public static final int CKSUMTYPE_HMAC_MD5_ARCFOUR = -138;
diff --git a/jdk/src/share/classes/sun/security/krb5/Config.java b/jdk/src/share/classes/sun/security/krb5/Config.java
index 117acb840..9873fcbef 100644
--- a/jdk/src/share/classes/sun/security/krb5/Config.java
+++ b/jdk/src/share/classes/sun/security/krb5/Config.java
@@ -1005,11 +1005,19 @@ public class Config {
} else if (input.startsWith("a") || (input.startsWith("A"))) {
// AES
if (input.equalsIgnoreCase("aes128-cts") ||
- input.equalsIgnoreCase("aes128-cts-hmac-sha1-96")) {
+ input.equalsIgnoreCase("aes128-sha1") ||
+ input.equalsIgnoreCase("aes128-cts-hmac-sha1-96")) {
result = EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96;
} else if (input.equalsIgnoreCase("aes256-cts") ||
- input.equalsIgnoreCase("aes256-cts-hmac-sha1-96")) {
+ input.equalsIgnoreCase("aes256-sha1") ||
+ input.equalsIgnoreCase("aes256-cts-hmac-sha1-96")) {
result = EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96;
+ } else if (input.equalsIgnoreCase("aes128-sha2") ||
+ input.equalsIgnoreCase("aes128-cts-hmac-sha256-128")) {
+ result = EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128;
+ } else if (input.equalsIgnoreCase("aes256-sha2") ||
+ input.equalsIgnoreCase("aes256-cts-hmac-sha384-192")) {
+ result = EncryptedData.ETYPE_AES256_CTS_HMAC_SHA384_192;
// ARCFOUR-HMAC
} else if (input.equalsIgnoreCase("arcfour-hmac") ||
input.equalsIgnoreCase("arcfour-hmac-md5")) {
@@ -1032,6 +1040,10 @@ public class Config {
result = Checksum.CKSUMTYPE_HMAC_SHA1_96_AES128;
} else if (input.equalsIgnoreCase("hmac-sha1-96-aes256")) {
result = Checksum.CKSUMTYPE_HMAC_SHA1_96_AES256;
+ } else if (input.equalsIgnoreCase("hmac-sha256-128-aes128")) {
+ result = Checksum.CKSUMTYPE_HMAC_SHA256_128_AES128;
+ } else if (input.equalsIgnoreCase("hmac-sha384-192-aes256")) {
+ result = Checksum.CKSUMTYPE_HMAC_SHA384_192_AES256;
} else if (input.equalsIgnoreCase("hmac-md5-rc4") ||
input.equalsIgnoreCase("hmac-md5-arcfour") ||
input.equalsIgnoreCase("hmac-md5-enc")) {
diff --git a/jdk/src/share/classes/sun/security/krb5/EncryptedData.java b/jdk/src/share/classes/sun/security/krb5/EncryptedData.java
index 7f93db2b9..91bb519aa 100644
--- a/jdk/src/share/classes/sun/security/krb5/EncryptedData.java
+++ b/jdk/src/share/classes/sun/security/krb5/EncryptedData.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -79,6 +79,12 @@ public class EncryptedData implements Cloneable {
public static final int
ETYPE_AES256_CTS_HMAC_SHA1_96 = 18; // 16 0 16
+ // rfc8009
+ public static final int
+ ETYPE_AES128_CTS_HMAC_SHA256_128 = 19; // 16 0 16
+ public static final int
+ ETYPE_AES256_CTS_HMAC_SHA384_192 = 20; // 16 0 16
+
/* used by self */
private EncryptedData() {
}
diff --git a/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java b/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java
index d484d7c55..627168e70 100644
--- a/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java
+++ b/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -252,6 +252,12 @@ public class EncryptionKey
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
return Aes256.stringToKey(password, salt, s2kparams);
+ case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128:
+ return Aes128Sha2.stringToKey(password, salt, s2kparams);
+
+ case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA384_192:
+ return Aes256Sha2.stringToKey(password, salt, s2kparams);
+
default:
throw new IllegalArgumentException("encryption type " +
EType.toString(keyType) + " not supported");
@@ -293,6 +299,15 @@ public class EncryptionKey
throw new IllegalArgumentException("Algorithm " + algorithm +
" not enabled");
}
+ } else if (algorithm.equalsIgnoreCase("aes128-cts-hmac-sha256-128")) {
+ keyType = EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128;
+ } else if (algorithm.equalsIgnoreCase("aes256-cts-hmac-sha384-192")) {
+ keyType = EncryptedData.ETYPE_AES256_CTS_HMAC_SHA384_192;
+ // validate if AES256 is enabled
+ if (!EType.isSupported(keyType)) {
+ throw new IllegalArgumentException("Algorithm " + algorithm +
+ " not enabled");
+ }
} else {
throw new IllegalArgumentException("Algorithm " + algorithm +
" not supported");
diff --git a/jdk/src/share/classes/sun/security/krb5/internal/crypto/Aes128CtsHmacSha2EType.java b/jdk/src/share/classes/sun/security/krb5/internal/crypto/Aes128CtsHmacSha2EType.java
new file mode 100644
index 000000000..cbd26ce34
--- /dev/null
+++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/Aes128CtsHmacSha2EType.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2017, 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.krb5.internal.crypto;
+
+import sun.security.krb5.KrbCryptoException;
+import sun.security.krb5.internal.*;
+import java.security.GeneralSecurityException;
+import sun.security.krb5.EncryptedData;
+import sun.security.krb5.Checksum;
+
+/*
+ * This class encapsulates the encryption type for aes128-cts-hmac-sha256-128
+ */
+
+public final class Aes128CtsHmacSha2EType extends EType {
+
+ public int eType() {
+ return EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128;
+ }
+
+ public int minimumPadSize() {
+ return 0;
+ }
+
+ public int confounderSize() {
+ return blockSize();
+ }
+
+ public int checksumType() {
+ return Checksum.CKSUMTYPE_HMAC_SHA256_128_AES128;
+ }
+
+ public int checksumSize() {
+ return Aes128Sha2.getChecksumLength();
+ }
+
+ public int blockSize() {
+ return 16;
+ }
+
+ public int keyType() {
+ return Krb5.KEYTYPE_AES;
+ }
+
+ public int keySize() {
+ return 16; // bytes
+ }
+
+ public byte[] encrypt(byte[] data, byte[] key, int usage)
+ throws KrbCryptoException {
+ byte[] ivec = new byte[blockSize()];
+ return encrypt(data, key, ivec, usage);
+ }
+
+ public byte[] encrypt(byte[] data, byte[] key, byte[] ivec, int usage)
+ throws KrbCryptoException {
+ try {
+ return Aes128Sha2.encrypt(key, usage, ivec, data, 0, data.length);
+ } catch (GeneralSecurityException e) {
+ KrbCryptoException ke = new KrbCryptoException(e.getMessage());
+ ke.initCause(e);
+ throw ke;
+ }
+ }
+
+ public byte[] decrypt(byte[] cipher, byte[] key, int usage)
+ throws KrbApErrException, KrbCryptoException {
+ byte[] ivec = new byte[blockSize()];
+ return decrypt(cipher, key, ivec, usage);
+ }
+
+ public byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage)
+ throws KrbApErrException, KrbCryptoException {
+ try {
+ return Aes128Sha2.decrypt(key, usage, ivec, cipher, 0, cipher.length);
+ } catch (GeneralSecurityException e) {
+ KrbCryptoException ke = new KrbCryptoException(e.getMessage());
+ ke.initCause(e);
+ throw ke;
+ }
+ }
+
+ // Override default, because our decrypted data does not return confounder
+ // Should eventually get rid of EType.decryptedData and
+ // EncryptedData.decryptedData altogether
+ public byte[] decryptedData(byte[] data) {
+ return data;
+ }
+}
diff --git a/jdk/src/share/classes/sun/security/krb5/internal/crypto/Aes128Sha2.java b/jdk/src/share/classes/sun/security/krb5/internal/crypto/Aes128Sha2.java
new file mode 100644
index 000000000..7941993c6
--- /dev/null
+++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/Aes128Sha2.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017, 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.krb5.internal.crypto;
+
+import sun.security.krb5.internal.crypto.dk.AesSha2DkCrypto;
+import sun.security.krb5.KrbCryptoException;
+import java.security.GeneralSecurityException;
+
+/**
+ * Class with static methods for doing aes128-cts-hmac-sha256-128 operations.
+ */
+
+public class Aes128Sha2 {
+ private static final AesSha2DkCrypto CRYPTO = new AesSha2DkCrypto(128);
+
+ private Aes128Sha2() {
+ }
+
+ public static byte[] stringToKey(char[] password, String salt, byte[] params)
+ throws GeneralSecurityException {
+ return CRYPTO.stringToKey(password, salt, params);
+ }
+
+ // in bytes
+ public static int getChecksumLength() {
+ return CRYPTO.getChecksumLength();
+ }
+
+ public static byte[] calculateChecksum(byte[] baseKey, int usage,
+ byte[] input, int start, int len) throws GeneralSecurityException {
+ return CRYPTO.calculateChecksum(baseKey, usage, input, start, len);
+ }
+
+ public static byte[] encrypt(byte[] baseKey, int usage,
+ byte[] ivec, byte[] plaintext, int start, int len)
+ throws GeneralSecurityException, KrbCryptoException {
+ return CRYPTO.encrypt(baseKey, usage, ivec, null /* new_ivec */,
+ plaintext, start, len);
+ }
+
+ /* Encrypt plaintext; do not add confounder, or checksum */
+ public static byte[] encryptRaw(byte[] baseKey, int usage,
+ byte[] ivec, byte[] plaintext, int start, int len)
+ throws GeneralSecurityException, KrbCryptoException {
+ return CRYPTO.encryptRaw(baseKey, usage, ivec, plaintext, start, len);
+ }
+
+ public static byte[] decrypt(byte[] baseKey, int usage, byte[] ivec,
+ byte[] ciphertext, int start, int len)
+ throws GeneralSecurityException {
+ return CRYPTO.decrypt(baseKey, usage, ivec, ciphertext, start, len);
+ }
+
+ /* Decrypt ciphertext; do not remove confounder, or check checksum */
+ public static byte[] decryptRaw(byte[] baseKey, int usage, byte[] ivec,
+ byte[] ciphertext, int start, int len)
+ throws GeneralSecurityException {
+ return CRYPTO.decryptRaw(baseKey, usage, ivec, ciphertext, start, len);
+ }
+};
diff --git a/jdk/src/share/classes/sun/security/krb5/internal/crypto/Aes256CtsHmacSha2EType.java b/jdk/src/share/classes/sun/security/krb5/internal/crypto/Aes256CtsHmacSha2EType.java
new file mode 100644
index 000000000..2ab783d08
--- /dev/null
+++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/Aes256CtsHmacSha2EType.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2017, 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.krb5.internal.crypto;
+
+import sun.security.krb5.KrbCryptoException;
+import sun.security.krb5.internal.*;
+import java.security.GeneralSecurityException;
+import sun.security.krb5.EncryptedData;
+import sun.security.krb5.Checksum;
+
+/*
+ * This class encapsulates the encryption type for aes256-cts-hmac-sha384-192
+ */
+
+public final class Aes256CtsHmacSha2EType extends EType {
+
+ public int eType() {
+ return EncryptedData.ETYPE_AES256_CTS_HMAC_SHA384_192;
+ }
+
+ public int minimumPadSize() {
+ return 0;
+ }
+
+ public int confounderSize() {
+ return blockSize();
+ }
+
+ public int checksumType() {
+ return Checksum.CKSUMTYPE_HMAC_SHA384_192_AES256;
+ }
+
+ public int checksumSize() {
+ return Aes256Sha2.getChecksumLength();
+ }
+
+ public int blockSize() {
+ return 16;
+ }
+
+ public int keyType() {
+ return Krb5.KEYTYPE_AES;
+ }
+
+ public int keySize() {
+ return 32; // bytes
+ }
+
+ public byte[] encrypt(byte[] data, byte[] key, int usage)
+ throws KrbCryptoException {
+ byte[] ivec = new byte[blockSize()];
+ return encrypt(data, key, ivec, usage);
+ }
+
+ public byte[] encrypt(byte[] data, byte[] key, byte[] ivec, int usage)
+ throws KrbCryptoException {
+ try {
+ return Aes256Sha2.encrypt(key, usage, ivec, data, 0, data.length);
+ } catch (GeneralSecurityException e) {
+ KrbCryptoException ke = new KrbCryptoException(e.getMessage());
+ ke.initCause(e);
+ throw ke;
+ }
+ }
+
+ public byte[] decrypt(byte[] cipher, byte[] key, int usage)
+ throws KrbApErrException, KrbCryptoException {
+ byte[] ivec = new byte[blockSize()];
+ return decrypt(cipher, key, ivec, usage);
+ }
+
+ public byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage)
+ throws KrbApErrException, KrbCryptoException {
+ try {
+ return Aes256Sha2.decrypt(key, usage, ivec, cipher, 0, cipher.length);
+ } catch (GeneralSecurityException e) {
+ KrbCryptoException ke = new KrbCryptoException(e.getMessage());
+ ke.initCause(e);
+ throw ke;
+ }
+ }
+
+ // Override default, because our decrypted data does not return confounder
+ // Should eventually get rid of EType.decryptedData and
+ // EncryptedData.decryptedData altogether
+ public byte[] decryptedData(byte[] data) {
+ return data;
+ }
+}
diff --git a/jdk/src/share/classes/sun/security/krb5/internal/crypto/Aes256Sha2.java b/jdk/src/share/classes/sun/security/krb5/internal/crypto/Aes256Sha2.java
new file mode 100644
index 000000000..434611662
--- /dev/null
+++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/Aes256Sha2.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2017, 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.krb5.internal.crypto;
+
+import sun.security.krb5.internal.crypto.dk.AesSha2DkCrypto;
+import sun.security.krb5.KrbCryptoException;
+import java.security.GeneralSecurityException;
+
+/**
+ * Class with static methods for doing aes256-cts-hmac-sha384-192 operations.
+ */
+
+public class Aes256Sha2 {
+ private static final AesSha2DkCrypto CRYPTO = new AesSha2DkCrypto(256);
+
+ private Aes256Sha2() {
+ }
+
+ public static byte[] stringToKey(char[] password, String salt, byte[] params)
+ throws GeneralSecurityException {
+ return CRYPTO.stringToKey(password, salt, params);
+ }
+
+ // in bytes
+ public static int getChecksumLength() {
+ return CRYPTO.getChecksumLength();
+ }
+
+ public static byte[] calculateChecksum(byte[] baseKey, int usage,
+ byte[] input, int start, int len) throws GeneralSecurityException {
+ return CRYPTO.calculateChecksum(baseKey, usage, input, start, len);
+ }
+
+ public static byte[] encrypt(byte[] baseKey, int usage,
+ byte[] ivec, byte[] plaintext, int start, int len)
+ throws GeneralSecurityException, KrbCryptoException {
+ return CRYPTO.encrypt(baseKey, usage, ivec, null /* new_ivec */,
+ plaintext, start, len);
+ }
+
+ /* Encrypt plaintext; do not add confounder, padding, or checksum */
+ public static byte[] encryptRaw(byte[] baseKey, int usage,
+ byte[] ivec, byte[] plaintext, int start, int len)
+ throws GeneralSecurityException, KrbCryptoException {
+ return CRYPTO.encryptRaw(baseKey, usage, ivec, plaintext, start, len);
+ }
+
+ public static byte[] decrypt(byte[] baseKey, int usage, byte[] ivec,
+ byte[] ciphertext, int start, int len)
+ throws GeneralSecurityException {
+ return CRYPTO.decrypt(baseKey, usage, ivec, ciphertext, start, len);
+ }
+
+ /*
+ * Decrypt ciphertext; do not remove confounder, padding, or check
+ * checksum
+ */
+ public static byte[] decryptRaw(byte[] baseKey, int usage, byte[] ivec,
+ byte[] ciphertext, int start, int len)
+ throws GeneralSecurityException {
+ return CRYPTO.decryptRaw(baseKey, usage, ivec, ciphertext, start, len);
+ }
+};
diff --git a/jdk/src/share/classes/sun/security/krb5/internal/crypto/CksumType.java b/jdk/src/share/classes/sun/security/krb5/internal/crypto/CksumType.java
index b7b06a99d..a437db94c 100644
--- a/jdk/src/share/classes/sun/security/krb5/internal/crypto/CksumType.java
+++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/CksumType.java
@@ -85,6 +85,18 @@ public abstract class CksumType {
"sun.security.krb5.internal.crypto.HmacSha1Aes256CksumType";
break;
+ case Checksum.CKSUMTYPE_HMAC_SHA256_128_AES128:
+ cksumType = new HmacSha2Aes128CksumType();
+ cksumTypeName =
+ "sun.security.krb5.internal.crypto.HmacSha2Aes128CksumType";
+ break;
+
+ case Checksum.CKSUMTYPE_HMAC_SHA384_192_AES256:
+ cksumType = new HmacSha2Aes256CksumType();
+ cksumTypeName =
+ "sun.security.krb5.internal.crypto.HmacSha2Aes256CksumType";
+ break;
+
case Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR:
cksumType = new HmacMd5ArcFourCksumType();
cksumTypeName =
diff --git a/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java b/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java
index ee59d2150..99dc65f1a 100644
--- a/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java
+++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java
@@ -106,7 +106,19 @@ public abstract class EType {
"sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType";
break;
- case EncryptedData.ETYPE_ARCFOUR_HMAC:
+ case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128:
+ eType = new Aes128CtsHmacSha2EType();
+ eTypeName =
+ "sun.security.krb5.internal.crypto.Aes128CtsHmacSha2EType";
+ break;
+
+ case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA384_192:
+ eType = new Aes256CtsHmacSha2EType();
+ eTypeName =
+ "sun.security.krb5.internal.crypto.Aes256CtsHmacSha2EType";
+ break;
+
+ case EncryptedData.ETYPE_ARCFOUR_HMAC:
eType = new ArcFourHmacEType();
eTypeName = "sun.security.krb5.internal.crypto.ArcFourHmacEType";
break;
@@ -189,20 +201,23 @@ public abstract class EType {
// is set to false.
private static final int[] BUILTIN_ETYPES = new int[] {
- EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96,
- EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
- EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
- EncryptedData.ETYPE_ARCFOUR_HMAC,
- EncryptedData.ETYPE_DES_CBC_CRC,
- EncryptedData.ETYPE_DES_CBC_MD5,
+ EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96,
+ EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
+ EncryptedData.ETYPE_AES256_CTS_HMAC_SHA384_192,
+ EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128,
+ EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
+ EncryptedData.ETYPE_ARCFOUR_HMAC,
+ EncryptedData.ETYPE_DES_CBC_CRC,
+ EncryptedData.ETYPE_DES_CBC_MD5,
};
private static final int[] BUILTIN_ETYPES_NOAES256 = new int[] {
- EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
- EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
- EncryptedData.ETYPE_ARCFOUR_HMAC,
- EncryptedData.ETYPE_DES_CBC_CRC,
- EncryptedData.ETYPE_DES_CBC_MD5,
+ EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
+ EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128,
+ EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
+ EncryptedData.ETYPE_ARCFOUR_HMAC,
+ EncryptedData.ETYPE_DES_CBC_CRC,
+ EncryptedData.ETYPE_DES_CBC_MD5,
};
@@ -363,7 +378,10 @@ public abstract class EType {
return "RC4 with HMAC";
case 24:
return "RC4 with HMAC EXP";
-
+ case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128:
+ return "AES128 CTS mode with HMAC SHA256-128";
+ case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA384_192:
+ return "AES256 CTS mode with HMAC SHA384-192";
}
return "Unknown (" + type + ")";
}
diff --git a/jdk/src/share/classes/sun/security/krb5/internal/crypto/HmacSha2Aes128CksumType.java b/jdk/src/share/classes/sun/security/krb5/internal/crypto/HmacSha2Aes128CksumType.java
new file mode 100644
index 000000000..68b841e6d
--- /dev/null
+++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/HmacSha2Aes128CksumType.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2017, 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.krb5.internal.crypto;
+
+import sun.security.krb5.Checksum;
+import sun.security.krb5.KrbCryptoException;
+import sun.security.krb5.internal.*;
+import java.security.GeneralSecurityException;
+
+/*
+ * This class encapsulates the checksum type for aes128-cts-sha256
+ */
+
+public class HmacSha2Aes128CksumType extends CksumType {
+
+ public HmacSha2Aes128CksumType() {
+ }
+
+ public int confounderSize() {
+ return 16;
+ }
+
+ public int cksumType() {
+ return Checksum.CKSUMTYPE_HMAC_SHA256_128_AES128;
+ }
+
+ public boolean isKeyed() {
+ return true;
+ }
+
+ public int cksumSize() {
+ return 16; // bytes
+ }
+
+ public int keyType() {
+ return Krb5.KEYTYPE_AES;
+ }
+
+ public int keySize() {
+ return 16; // bytes
+ }
+
+ /**
+ * Calculates keyed checksum.
+ * @param data the data used to generate the checksum.
+ * @param size length of the data.
+ * @param key the key used to encrypt the checksum.
+ * @return keyed checksum.
+ */
+ public byte[] calculateChecksum(byte[] data, int size, byte[] key,
+ int usage) throws KrbCryptoException {
+
+ try {
+ return Aes128Sha2.calculateChecksum(key, usage, data, 0, size);
+ } catch (GeneralSecurityException e) {
+ KrbCryptoException ke = new KrbCryptoException(e.getMessage());
+ ke.initCause(e);
+ throw ke;
+ }
+ }
+
+ /**
+ * Verifies keyed checksum.
+ * @param data the data.
+ * @param size the length of data.
+ * @param key the key used to encrypt the checksum.
+ * @param checksum the checksum.
+ * @return true if verification is successful.
+ */
+ public boolean verifyChecksum(byte[] data, int size,
+ byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
+
+ try {
+ byte[] newCksum = Aes128Sha2.calculateChecksum(key, usage,
+ data, 0, size);
+ return isChecksumEqual(checksum, newCksum);
+ } catch (GeneralSecurityException e) {
+ KrbCryptoException ke = new KrbCryptoException(e.getMessage());
+ ke.initCause(e);
+ throw ke;
+ }
+ }
+}
diff --git a/jdk/src/share/classes/sun/security/krb5/internal/crypto/HmacSha2Aes256CksumType.java b/jdk/src/share/classes/sun/security/krb5/internal/crypto/HmacSha2Aes256CksumType.java
new file mode 100644
index 000000000..23772205c
--- /dev/null
+++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/HmacSha2Aes256CksumType.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2017, 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.krb5.internal.crypto;
+
+import sun.security.krb5.Checksum;
+import sun.security.krb5.KrbCryptoException;
+import sun.security.krb5.internal.*;
+import java.security.GeneralSecurityException;
+
+/*
+ * This class encapsulates the checksum type for aes256-cts-sha384
+ */
+
+public class HmacSha2Aes256CksumType extends CksumType {
+
+ public HmacSha2Aes256CksumType() {
+ }
+
+ public int confounderSize() {
+ return 16;
+ }
+
+ public int cksumType() {
+ return Checksum.CKSUMTYPE_HMAC_SHA384_192_AES256;
+ }
+
+ public boolean isKeyed() {
+ return true;
+ }
+
+ public int cksumSize() {
+ return 24; // bytes
+ }
+
+ public int keyType() {
+ return Krb5.KEYTYPE_AES;
+ }
+
+ public int keySize() {
+ return 32; // bytes
+ }
+
+ /**
+ * Calculates keyed checksum.
+ * @param data the data used to generate the checksum.
+ * @param size length of the data.
+ * @param key the key used to encrypt the checksum.
+ * @return keyed checksum.
+ */
+ public byte[] calculateChecksum(byte[] data, int size, byte[] key,
+ int usage) throws KrbCryptoException {
+
+ try {
+ return Aes256Sha2.calculateChecksum(key, usage, data, 0, size);
+ } catch (GeneralSecurityException e) {
+ KrbCryptoException ke = new KrbCryptoException(e.getMessage());
+ ke.initCause(e);
+ throw ke;
+ }
+ }
+
+ /**
+ * Verifies keyed checksum.
+ * @param data the data.
+ * @param size the length of data.
+ * @param key the key used to encrypt the checksum.
+ * @param checksum the checksum.
+ * @return true if verification is successful.
+ */
+ public boolean verifyChecksum(byte[] data, int size,
+ byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
+
+ try {
+ byte[] newCksum = Aes256Sha2.calculateChecksum(key, usage, data,
+ 0, size);
+ return isChecksumEqual(checksum, newCksum);
+ } catch (GeneralSecurityException e) {
+ KrbCryptoException ke = new KrbCryptoException(e.getMessage());
+ ke.initCause(e);
+ throw ke;
+ }
+ }
+}
diff --git a/jdk/src/share/classes/sun/security/krb5/internal/crypto/dk/AesSha2DkCrypto.java b/jdk/src/share/classes/sun/security/krb5/internal/crypto/dk/AesSha2DkCrypto.java
new file mode 100644
index 000000000..f46e18509
--- /dev/null
+++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/dk/AesSha2DkCrypto.java
@@ -0,0 +1,541 @@
+/*
+ * Copyright (c) 2017, 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.krb5.internal.crypto.dk;
+
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
+import java.security.GeneralSecurityException;
+import sun.security.krb5.KrbCryptoException;
+import sun.security.krb5.Confounder;
+import sun.security.krb5.internal.crypto.KeyUsage;
+import java.util.Arrays;
+
+/**
+ * This class provides the implementation of AES Encryption with
+ * HMAC-SHA2 for Kerberos 5
+ * https://tools.ietf.org/html/rfc8009
+ *
+ * Algorithm profile described in [KCRYPTO]:
+ * +--------------------------------------------------------------------+
+ * | protocol key format 128- or 256-bit string |
+ * | |
+ * | string-to-key function PBKDF2+DK with variable |
+ * | iteration count (see |
+ * | above) |
+ * | |
+ * | default string-to-key parameters 00 00 80 00 |
+ * | |
+ * | key-generation seed length key size |
+ * | |
+ * | random-to-key function identity function |
+ * | |
+ * | hash function, H SHA-256 / SHA-384 |
+ * | |
+ * | HMAC output size, h 16/24 octets |
+ * | |
+ * | message block size, m 1 octet |
+ * | |
+ * | encryption/decryption functions, AES in CBC-CTS mode |
+ * | E and D (cipher block size 16 |
+ * | octets), with next to |
+ * | last block as CBC-style |
+ * | ivec |
+ * +--------------------------------------------------------------------+
+ *
+ * Supports aes128-cts-hmac-sha256-128 and aes256-cts-hmac-sha384-192
+ */
+
+public class AesSha2DkCrypto extends DkCrypto {
+
+ private static final boolean debug = false;
+
+ private static final int BLOCK_SIZE = 16;
+ private static final int DEFAULT_ITERATION_COUNT = 32768;
+ private static final byte[] ZERO_IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ private static final byte[] ETYPE_NAME_128 =
+ "aes128-cts-hmac-sha256-128".getBytes();
+ private static final byte[] ETYPE_NAME_256 =
+ "aes256-cts-hmac-sha384-192".getBytes();
+
+ private final int hashSize;
+ private final int keyLength;
+
+ public AesSha2DkCrypto(int length) {
+ keyLength = length;
+ hashSize = (length == 128?128:192)/8;
+ }
+
+ protected int getKeySeedLength() {
+ return keyLength; // bits; AES key material
+ }
+
+ public byte[] stringToKey(char[] password, String salt, byte[] s2kparams)
+ throws GeneralSecurityException {
+
+ byte[] saltUtf8 = null;
+ try {
+ saltUtf8 = salt.getBytes("UTF-8");
+ return stringToKey(password, saltUtf8, s2kparams);
+ } catch (Exception e) {
+ return null;
+ } finally {
+ if (saltUtf8 != null) {
+ Arrays.fill(saltUtf8, (byte)0);
+ }
+ }
+ }
+
+ // https://tools.ietf.org/html/rfc8009#section-4
+ private byte[] stringToKey(char[] secret, byte[] salt, byte[] params)
+ throws GeneralSecurityException {
+
+ int iter_count = DEFAULT_ITERATION_COUNT;
+ if (params != null) {
+ if (params.length != 4) {
+ throw new RuntimeException("Invalid parameter to stringToKey");
+ }
+ iter_count = readBigEndian(params, 0, 4);
+ }
+
+ byte[] saltp = new byte[26 + 1 + salt.length];
+ if (keyLength == 128) {
+ System.arraycopy(ETYPE_NAME_128, 0, saltp, 0, 26);
+ } else {
+ System.arraycopy(ETYPE_NAME_256, 0, saltp, 0, 26);
+ }
+ System.arraycopy(salt, 0, saltp, 27, salt.length);
+ byte[] tmpKey = randomToKey(PBKDF2(secret, saltp, iter_count,
+ getKeySeedLength()));
+ byte[] result = dk(tmpKey, KERBEROS_CONSTANT);
+ return result;
+ }
+
+ protected byte[] randomToKey(byte[] in) {
+ // simple identity operation
+ return in;
+ }
+
+ /*
+ * https://tools.ietf.org/html/rfc8009#section-3 defines
+ * a new key derivation function:
+ *
+ * KDF-HMAC-SHA2(key, label, k) = k-truncate(K1)
+ * K1 = HMAC-SHA-256(key, 0x00000001 | label | 0x00 | k) or
+ * K1 = HMAC-SHA-384(key, 0x00000001 | label | 0x00 | k)
+ *
+ * where label is constant below.
+ */
+ protected byte[] dr(byte[] key, byte[] constant)
+ throws GeneralSecurityException {
+ byte[] result;
+ byte[] input = new byte[constant.length + 9];
+ // 0x00000001 at the beginning
+ input[3] = 1;
+ // label follows
+ System.arraycopy(constant, 0, input, 4, constant.length);
+ SecretKeySpec tkey = new SecretKeySpec(key, "HMAC");
+ Mac mac = Mac.getInstance(
+ keyLength == 128? "HmacSHA256": "HmacSHA384");
+ mac.init(tkey);
+
+ int k;
+ if (keyLength == 128) {
+ // key length for enc and hmac both 128
+ k = 128;
+ } else {
+ byte last = constant[constant.length-1];
+ if (last == (byte)0x99 || last == (byte)0x55) {
+ // 192 for hmac
+ k = 192;
+ } else {
+ // 256 for enc
+ k = 256;
+ }
+ }
+ // 0x00 and k at the end
+ input[input.length - 1] = (byte)(k);
+ input[input.length - 2] = (byte)(k / 256);
+
+ result = mac.doFinal(input);
+ return Arrays.copyOf(result, k / 8);
+ }
+
+ protected Cipher getCipher(byte[] key, byte[] ivec, int mode)
+ throws GeneralSecurityException {
+
+ // IV
+ if (ivec == null) {
+ ivec = ZERO_IV;
+ }
+ SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
+ Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+ IvParameterSpec encIv = new IvParameterSpec(ivec, 0, ivec.length);
+ cipher.init(mode, secretKey, encIv);
+ return cipher;
+ }
+
+ // get an instance of the AES Cipher in CTS mode
+ public int getChecksumLength() {
+ return hashSize; // bytes
+ }
+
+ /**
+ * Get the truncated HMAC
+ */
+ protected byte[] getHmac(byte[] key, byte[] msg)
+ throws GeneralSecurityException {
+
+ SecretKey keyKi = new SecretKeySpec(key, "HMAC");
+ Mac m = Mac.getInstance(keyLength == 128 ? "HmacSHA256" : "HmacSHA384");
+ m.init(keyKi);
+
+ // generate hash
+ byte[] hash = m.doFinal(msg);
+
+ // truncate hash
+ byte[] output = new byte[hashSize];
+ System.arraycopy(hash, 0, output, 0, hashSize);
+ return output;
+ }
+
+ private byte[] deriveKey(byte[] baseKey, int usage, byte type)
+ throws GeneralSecurityException {
+ byte[] constant = new byte[5];
+ constant[0] = (byte) ((usage>>24)&0xff);
+ constant[1] = (byte) ((usage>>16)&0xff);
+ constant[2] = (byte) ((usage>>8)&0xff);
+ constant[3] = (byte) (usage&0xff);
+ constant[4] = type;
+ return dk(baseKey, constant);
+ }
+
+ /**
+ * Calculate the checksum
+ */
+ public byte[] calculateChecksum(byte[] baseKey, int usage, byte[] input,
+ int start, int len) throws GeneralSecurityException {
+
+ if (!KeyUsage.isValid(usage)) {
+ throw new GeneralSecurityException("Invalid key usage number: "
+ + usage);
+ }
+
+ byte[] Kc = deriveKey(baseKey, usage, (byte) 0x99); // Checksum key
+ if (debug) {
+ System.err.println("usage: " + usage);
+ traceOutput("input", input, start, Math.min(len, 32));
+ traceOutput("baseKey", baseKey, 0, baseKey.length);
+ traceOutput("Kc", Kc, 0, Kc.length);
+ }
+
+ try {
+ // Generate checksum
+ // H1 = HMAC(Kc, input)
+ byte[] hmac = getHmac(Kc, input);
+ if (debug) {
+ traceOutput("hmac", hmac, 0, hmac.length);
+ }
+ if (hmac.length == getChecksumLength()) {
+ return hmac;
+ } else if (hmac.length > getChecksumLength()) {
+ byte[] buf = new byte[getChecksumLength()];
+ System.arraycopy(hmac, 0, buf, 0, buf.length);
+ return buf;
+ } else {
+ throw new GeneralSecurityException("checksum size too short: " +
+ hmac.length + "; expecting : " + getChecksumLength());
+ }
+ } finally {
+ Arrays.fill(Kc, 0, Kc.length, (byte)0);
+ }
+ }
+
+ /**
+ * Performs encryption using derived key; adds confounder.
+ */
+ public byte[] encrypt(byte[] baseKey, int usage,
+ byte[] ivec, byte[] new_ivec, byte[] plaintext, int start, int len)
+ throws GeneralSecurityException, KrbCryptoException {
+
+ if (!KeyUsage.isValid(usage)) {
+ throw new GeneralSecurityException("Invalid key usage number: "
+ + usage);
+ }
+ byte[] output = encryptCTS(baseKey, usage, ivec, new_ivec, plaintext,
+ start, len, true);
+ return output;
+ }
+
+ /**
+ * Performs encryption using derived key; does not add confounder.
+ */
+ public byte[] encryptRaw(byte[] baseKey, int usage,
+ byte[] ivec, byte[] plaintext, int start, int len)
+ throws GeneralSecurityException, KrbCryptoException {
+
+ if (!KeyUsage.isValid(usage)) {
+ throw new GeneralSecurityException("Invalid key usage number: "
+ + usage);
+ }
+ byte[] output = encryptCTS(baseKey, usage, ivec, null, plaintext,
+ start, len, false);
+ return output;
+ }
+
+ /**
+ * @param baseKey key from which keys are to be derived using usage
+ * @param ciphertext E(Ke, conf | plaintext | padding, ivec) | H1[1..h]
+ */
+ public byte[] decrypt(byte[] baseKey, int usage, byte[] ivec,
+ byte[] ciphertext, int start, int len) throws GeneralSecurityException {
+
+ if (!KeyUsage.isValid(usage)) {
+ throw new GeneralSecurityException("Invalid key usage number: "
+ + usage);
+ }
+ byte[] output = decryptCTS(baseKey, usage, ivec, ciphertext,
+ start, len, true);
+ return output;
+ }
+
+ /**
+ * Decrypts data using specified key and initial vector.
+ * @param baseKey encryption key to use
+ * @param ciphertext encrypted data to be decrypted
+ * @param usage ignored
+ */
+ public byte[] decryptRaw(byte[] baseKey, int usage, byte[] ivec,
+ byte[] ciphertext, int start, int len)
+ throws GeneralSecurityException {
+
+ if (!KeyUsage.isValid(usage)) {
+ throw new GeneralSecurityException("Invalid key usage number: "
+ + usage);
+ }
+ byte[] output = decryptCTS(baseKey, usage, ivec, ciphertext,
+ start, len, false);
+ return output;
+ }
+
+ /**
+ * Encrypt AES in CBC-CTS mode using derived keys.
+ */
+ private byte[] encryptCTS(byte[] baseKey, int usage, byte[] ivec,
+ byte[] new_ivec, byte[] plaintext, int start, int len,
+ boolean confounder_exists)
+ throws GeneralSecurityException, KrbCryptoException {
+
+ byte[] Ke = null;
+ byte[] Ki = null;
+
+ if (debug) {
+ System.err.println("usage: " + usage);
+ if (ivec != null) {
+ traceOutput("old_state.ivec", ivec, 0, ivec.length);
+ }
+ traceOutput("plaintext", plaintext, start, Math.min(len, 32));
+ traceOutput("baseKey", baseKey, 0, baseKey.length);
+ }
+
+ try {
+ Ke = deriveKey(baseKey, usage, (byte) 0xaa); // Encryption key
+
+ byte[] toBeEncrypted = null;
+ if (confounder_exists) {
+ byte[] confounder = Confounder.bytes(BLOCK_SIZE);
+ toBeEncrypted = new byte[confounder.length + len];
+ System.arraycopy(confounder, 0, toBeEncrypted,
+ 0, confounder.length);
+ System.arraycopy(plaintext, start, toBeEncrypted,
+ confounder.length, len);
+ } else {
+ toBeEncrypted = new byte[len];
+ System.arraycopy(plaintext, start, toBeEncrypted, 0, len);
+ }
+
+ // encryptedData + HMAC
+ byte[] output = new byte[toBeEncrypted.length + hashSize];
+
+ // AES in JCE
+ Cipher cipher = Cipher.getInstance("AES/CTS/NoPadding");
+ SecretKeySpec secretKey = new SecretKeySpec(Ke, "AES");
+ IvParameterSpec encIv = new IvParameterSpec(ivec, 0, ivec.length);
+ cipher.init(Cipher.ENCRYPT_MODE, secretKey, encIv);
+ cipher.doFinal(toBeEncrypted, 0, toBeEncrypted.length, output);
+
+ Ki = deriveKey(baseKey, usage, (byte) 0x55);
+ if (debug) {
+ traceOutput("Ki", Ki, 0, Ke.length);
+ }
+
+ // Generate checksum
+ // H = HMAC(Ki, IV | C)
+ byte[] msg = Arrays.copyOf(ivec, ivec.length + toBeEncrypted.length);
+ System.arraycopy(output, 0, msg, ivec.length, toBeEncrypted.length);
+ byte[] hmac = getHmac(Ki, msg);
+
+ // encryptedData + HMAC
+ System.arraycopy(hmac, 0, output, toBeEncrypted.length,
+ hmac.length);
+ return output;
+ } finally {
+ if (Ke != null) {
+ Arrays.fill(Ke, 0, Ke.length, (byte) 0);
+ }
+ if (Ki != null) {
+ Arrays.fill(Ki, 0, Ki.length, (byte) 0);
+ }
+ }
+ }
+
+ /**
+ * Decrypt AES in CBC-CTS mode using derived keys.
+ */
+ private byte[] decryptCTS(byte[] baseKey, int usage, byte[] ivec,
+ byte[] ciphertext, int start, int len, boolean confounder_exists)
+ throws GeneralSecurityException {
+
+ byte[] Ke = null;
+ byte[] Ki = null;
+
+ try {
+ Ke = deriveKey(baseKey, usage, (byte) 0xaa); // Encryption key
+
+ if (debug) {
+ System.err.println("usage: " + usage);
+ if (ivec != null) {
+ traceOutput("old_state.ivec", ivec, 0, ivec.length);
+ }
+ traceOutput("ciphertext", ciphertext, start, Math.min(len, 32));
+ traceOutput("baseKey", baseKey, 0, baseKey.length);
+ traceOutput("Ke", Ke, 0, Ke.length);
+ }
+
+ // Decrypt [confounder | plaintext ] (without checksum)
+
+ // AES in JCE
+ Cipher cipher = Cipher.getInstance("AES/CTS/NoPadding");
+ SecretKeySpec secretKey = new SecretKeySpec(Ke, "AES");
+ IvParameterSpec encIv = new IvParameterSpec(ivec, 0, ivec.length);
+ cipher.init(Cipher.DECRYPT_MODE, secretKey, encIv);
+ byte[] plaintext = cipher.doFinal(ciphertext, start, len-hashSize);
+
+ if (debug) {
+ traceOutput("AES PlainText", plaintext, 0,
+ Math.min(plaintext.length, 32));
+ }
+
+ Ki = deriveKey(baseKey, usage, (byte) 0x55); // Integrity key
+ if (debug) {
+ traceOutput("Ki", Ki, 0, Ke.length);
+ }
+
+ // Verify checksum
+ // H = HMAC(Ki, IV | C)
+ byte[] msg = Arrays.copyOf(ivec, ivec.length + len-hashSize);
+ System.arraycopy(ciphertext, start, msg, ivec.length, len-hashSize);
+ byte[] calculatedHmac = getHmac(Ki, msg);
+ int hmacOffset = start + len - hashSize;
+ if (debug) {
+ traceOutput("calculated Hmac", calculatedHmac,
+ 0, calculatedHmac.length);
+ traceOutput("message Hmac", ciphertext, hmacOffset, hashSize);
+ }
+ boolean cksumFailed = false;
+ if (calculatedHmac.length >= hashSize) {
+ for (int i = 0; i < hashSize; i++) {
+ if (calculatedHmac[i] != ciphertext[hmacOffset+i]) {
+ cksumFailed = true;
+ if (debug) {
+ System.err.println("Checksum failed !");
+ }
+ break;
+ }
+ }
+ }
+ if (cksumFailed) {
+ throw new GeneralSecurityException("Checksum failed");
+ }
+
+ if (confounder_exists) {
+ // Get rid of confounder
+ // [ confounder | plaintext ]
+ byte[] output = new byte[plaintext.length - BLOCK_SIZE];
+ System.arraycopy(plaintext, BLOCK_SIZE, output,
+ 0, output.length);
+ return output;
+ } else {
+ return plaintext;
+ }
+ } finally {
+ if (Ke != null) {
+ Arrays.fill(Ke, 0, Ke.length, (byte) 0);
+ }
+ if (Ki != null) {
+ Arrays.fill(Ki, 0, Ki.length, (byte) 0);
+ }
+ }
+ }
+
+ /*
+ * Invoke the PKCS#5 PBKDF2 algorithm
+ */
+ private static byte[] PBKDF2(char[] secret, byte[] salt,
+ int count, int keyLength) throws GeneralSecurityException {
+
+ PBEKeySpec keySpec = new PBEKeySpec(secret, salt, count, keyLength);
+ SecretKeyFactory skf =
+ SecretKeyFactory.getInstance(keyLength == 128 ?
+ "PBKDF2WithHmacSHA256" : "PBKDF2WithHmacSHA384");
+ SecretKey key = skf.generateSecret(keySpec);
+ byte[] result = key.getEncoded();
+
+ return result;
+ }
+
+ public static final int readBigEndian(byte[] data, int pos, int size) {
+ int retVal = 0;
+ int shifter = (size-1)*8;
+ while (size > 0) {
+ retVal += (data[pos] & 0xff) << shifter;
+ shifter -= 8;
+ pos++;
+ size--;
+ }
+ return retVal;
+ }
+
+}
diff --git a/jdk/src/share/classes/sun/security/krb5/internal/crypto/dk/DkCrypto.java b/jdk/src/share/classes/sun/security/krb5/internal/crypto/dk/DkCrypto.java
index 506d8749c..e0d8bca0e 100644
--- a/jdk/src/share/classes/sun/security/krb5/internal/crypto/dk/DkCrypto.java
+++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/dk/DkCrypto.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -478,7 +478,7 @@ public abstract class DkCrypto {
*
* DR(Key, Constant) = k-truncate(K1 | K2 | K3 | K4 ...)
*/
- private byte[] dr(byte[] key, byte[] constant)
+ protected byte[] dr(byte[] key, byte[] constant)
throws GeneralSecurityException {
Cipher encCipher = getCipher(key, null, Cipher.ENCRYPT_MODE);
@@ -668,7 +668,7 @@ public abstract class DkCrypto {
new HexDumpEncoder().encodeBuffer(
new ByteArrayInputStream(output, offset, len), out);
- System.err.println(traceTag + ":" + out.toString());
+ System.err.println(traceTag + ":\n" + out.toString());
} catch (Exception e) {
}
}
diff --git a/jdk/test/sun/security/krb5/auto/BasicKrb5Test.java b/jdk/test/sun/security/krb5/auto/BasicKrb5Test.java
index f18ae1642..63b5a9f07 100644
--- a/jdk/test/sun/security/krb5/auto/BasicKrb5Test.java
+++ b/jdk/test/sun/security/krb5/auto/BasicKrb5Test.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2017, 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,44 +23,50 @@
/*
* @test
- * @bug 6706974
+ * @bug 6706974 8014628
* @summary Add krb5 test infrastructure
* @compile -XDignore.symbol.file BasicKrb5Test.java
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des-cbc-crc
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des-cbc-md5
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des3-cbc-sha1
- * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes128-cts
- * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes256-cts
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes128-sha1
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes256-sha1
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes128-sha2
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes256-sha2
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test rc4-hmac
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test -s
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des-cbc-crc -s
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des-cbc-md5 -s
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des3-cbc-sha1 -s
- * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes128-cts -s
- * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes256-cts -s
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes128-sha1 -s
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes256-sha1 -s
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes128-sha2 -s
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes256-sha2 -s
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test rc4-hmac -s
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test -C
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des-cbc-crc -C
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des-cbc-md5 -C
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des3-cbc-sha1 -C
- * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes128-cts -C
- * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes256-cts -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes128-sha1 -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes256-sha1 -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes128-sha2 -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes256-sha2 -C
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test rc4-hmac -C
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test -s -C
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des-cbc-crc -s -C
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des-cbc-md5 -s -C
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des3-cbc-sha1 -s -C
- * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes128-cts -s -C
- * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes256-cts -s -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes128-sha1 -s -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes256-sha1 -s -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes128-sha2 -s -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes256-sha2 -s -C
* @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test rc4-hmac -s -C
*/
import org.ietf.jgss.GSSName;
import sun.security.jgss.GSSUtil;
-import sun.security.krb5.Config;
import sun.security.krb5.KrbException;
-import sun.security.krb5.internal.crypto.EType;
/**
* Basic JGSS/krb5 test with 3 parties: client, server, backend server. Each
diff --git a/jdk/test/sun/security/krb5/auto/KDC.java b/jdk/test/sun/security/krb5/auto/KDC.java
index 34dd482a2..b60bc0609 100644
--- a/jdk/test/sun/security/krb5/auto/KDC.java
+++ b/jdk/test/sun/security/krb5/auto/KDC.java
@@ -633,19 +633,7 @@ public class KDC {
*/
private static EncryptionKey generateRandomKey(int eType)
throws KrbException {
- // Is 32 enough for AES256? I should have generated the keys directly
- // but different cryptos have different rules on what keys are valid.
- char[] pass = randomPassword();
- String algo;
- switch (eType) {
- case EncryptedData.ETYPE_DES_CBC_MD5: algo = "DES"; break;
- case EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD: algo = "DESede"; break;
- case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96: algo = "AES128"; break;
- case EncryptedData.ETYPE_ARCFOUR_HMAC: algo = "ArcFourHMAC"; break;
- case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96: algo = "AES256"; break;
- default: algo = "DES"; break;
- }
- return new EncryptionKey(pass, "NOTHING", algo); // Silly
+ return genKey0(randomPassword(), "NOTHING", null, eType, null);
}
/**
@@ -709,6 +697,8 @@ public class KDC {
switch (etype) {
case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
+ case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128:
+ case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA384_192:
String pn = p.toString();
if (p.getRealmString() == null) {
pn = pn + "@" + getRealm();
@@ -716,7 +706,11 @@ public class KDC {
if (s2kparamses.containsKey(pn)) {
return s2kparamses.get(pn);
}
- return new byte[] {0, 0, 0x10, 0};
+ if (etype < EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128) {
+ return new byte[]{0, 0, 0x10, 0};
+ } else {
+ return new byte[]{0, 0, (byte) 0x80, 0};
+ }
default:
return null;
}
@@ -744,9 +738,8 @@ public class KDC {
kvno = pass[pass.length-1] - '0';
}
}
- return new EncryptionKey(EncryptionKeyDotStringToKey(
- getPassword(p, server), getSalt(p), getParams(p, etype), etype),
- etype, kvno);
+ return genKey0(getPassword(p, server), getSalt(p),
+ getParams(p, etype), etype, kvno);
} catch (KrbException ke) {
throw ke;
} catch (Exception e) {
@@ -763,6 +756,17 @@ public class KDC {
return new KerberosTime(new Date().getTime() + offset * 1000L);
}
+ /**
+ * Generates key from password.
+ */
+ private static EncryptionKey genKey0(
+ char[] pass, String salt, byte[] s2kparams,
+ int etype, Integer kvno) throws KrbException {
+ return new EncryptionKey(EncryptionKeyDotStringToKey(
+ pass, salt, s2kparams, etype),
+ etype, kvno);
+ }
+
/**
* Processes an incoming request and generates a response.
* @param in the request
@@ -1258,8 +1262,8 @@ public class KDC {
}
boolean allOld = true;
for (int i: eTypes) {
- if (i == EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96 ||
- i == EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96) {
+ if (i >= EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96 &&
+ i != EncryptedData.ETYPE_ARCFOUR_HMAC) {
allOld = false;
break;
}
diff --git a/jdk/test/sun/security/krb5/auto/ReplayCacheTestProc.java b/jdk/test/sun/security/krb5/auto/ReplayCacheTestProc.java
index 6413e155b..b59832f73 100644
--- a/jdk/test/sun/security/krb5/auto/ReplayCacheTestProc.java
+++ b/jdk/test/sun/security/krb5/auto/ReplayCacheTestProc.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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 7152176 8168518
+ * @bug 7152176 8168518 8014628
* @summary More krb5 tests
* @library ../../../../java/security/testlibrary/ /test/lib
* @compile -XDignore.symbol.file ReplayCacheTestProc.java
@@ -139,8 +139,13 @@ public class ReplayCacheTestProc {
kdc.addPrincipalRandKey(service(i));
}
+ // Native lib might not support aes-sha2
+ KDC.saveConfig(OneKDC.KRB5_CONF, kdc,
+ "default_tkt_enctypes = aes128-cts",
+ "default_tgs_enctypes = aes128-cts");
+
+ // Write KTAB after krb5.conf so it contains no aes-sha2 keys
kdc.writeKtab(OneKDC.KTAB);
- KDC.saveConfig(OneKDC.KRB5_CONF, kdc);
pi = Proc.create("ReplayCacheTestProc").debug("C")
.args("initiator")
diff --git a/jdk/test/sun/security/krb5/etype/ETypeOrder.java b/jdk/test/sun/security/krb5/etype/ETypeOrder.java
index 9437b16ed..be36d6372 100644
--- a/jdk/test/sun/security/krb5/etype/ETypeOrder.java
+++ b/jdk/test/sun/security/krb5/etype/ETypeOrder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2017, 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
@@ -37,7 +37,7 @@ public class ETypeOrder {
int[] etypes = EType.getBuiltInDefaults();
// Reference order, note that 2 is not implemented in Java
- int correct[] = { 18, 17, 16, 23, 1, 3, 2 };
+ int correct[] = { 18, 17, 20, 19, 16, 23, 1, 3, 2 };
int match = 0;
loopi: for (int i=0; i<etypes.length; i++) {
diff --git a/jdk/test/sun/security/krb5/etype/KerberosAesSha2.java b/jdk/test/sun/security/krb5/etype/KerberosAesSha2.java
new file mode 100644
index 000000000..bb2b31886
--- /dev/null
+++ b/jdk/test/sun/security/krb5/etype/KerberosAesSha2.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2017, 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 8014628
+ * @modules java.base/sun.security.util
+ * java.security.jgss/sun.security.krb5.internal.crypto.dk:+open
+ * @summary https://tools.ietf.org/html/rfc8009 Test Vectors
+ */
+
+import javax.crypto.Cipher;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+import sun.security.krb5.internal.crypto.dk.AesSha2DkCrypto;
+import sun.misc.HexDumpEncoder;
+
+public class KerberosAesSha2 {
+
+ public static void main(String[] args) throws Exception {
+
+ AesSha2DkCrypto dk128 = new AesSha2DkCrypto(128);
+ AesSha2DkCrypto dk256 = new AesSha2DkCrypto(256);
+
+ boolean aes256ok = Cipher.getMaxAllowedKeyLength("AES") >= 256;
+
+ // Sample results for string-to-key conversion:
+ char[] pass = "password".toCharArray();
+ byte[] salt = cat(
+ hex("10 DF 9D D7 83 E5 BC 8A CE A1 73 0E 74 35 5F 61"),
+ "ATHENA.MIT.EDUraeburn".getBytes());
+
+ check(stringToKey(dk128, pass, salt, null),
+ hex("08 9B CA 48 B1 05 EA 6E A7 7C A5 D2 F3 9D C5 E7"));
+
+ check(stringToKey(dk256, pass, salt, null),
+ hex("45 BD 80 6D BF 6A 83 3A 9C FF C1 C9 45 89 A2 22\n" +
+ "36 7A 79 BC 21 C4 13 71 89 06 E9 F5 78 A7 84 67"));
+
+ // Sample results for key derivation:
+ byte[] bk16 = hex("37 05 D9 60 80 C1 77 28 A0 E8 00 EA B6 E0 D2 3C");
+
+ check(deriveKey(dk128, bk16, 2, (byte) 0x99),
+ hex("B3 1A 01 8A 48 F5 47 76 F4 03 E9 A3 96 32 5D C3"));
+ check(deriveKey(dk128, bk16, 2, (byte) 0xaa),
+ hex("9B 19 7D D1 E8 C5 60 9D 6E 67 C3 E3 7C 62 C7 2E"));
+ check(deriveKey(dk128, bk16, 2, (byte) 0x55),
+ hex("9F DA 0E 56 AB 2D 85 E1 56 9A 68 86 96 C2 6A 6C"));
+
+ byte[] bk32 = hex(
+ "6D 40 4D 37 FA F7 9F 9D F0 D3 35 68 D3 20 66 98\n" +
+ "00 EB 48 36 47 2E A8 A0 26 D1 6B 71 82 46 0C 52");
+
+ check(deriveKey(dk256, bk32, 2, (byte) 0x99), hex(
+ "EF 57 18 BE 86 CC 84 96 3D 8B BB 50 31 E9 F5 C4\n" +
+ "BA 41 F2 8F AF 69 E7 3D"));
+ check(deriveKey(dk256, bk32, 2, (byte) 0xaa), hex(
+ "56 AB 22 BE E6 3D 82 D7 BC 52 27 F6 77 3F 8E A7\n" +
+ "A5 EB 1C 82 51 60 C3 83 12 98 0C 44 2E 5C 7E 49"));
+ check(deriveKey(dk256, bk32, 2, (byte) 0x55), hex(
+ "69 B1 65 14 E3 CD 8E 56 B8 20 10 D5 C7 30 12 B6\n" +
+ "22 C4 D0 0F FC 23 ED 1F"));
+
+ // Sample encryptions (all using the default cipher state):
+
+ check(enc(dk128, hex("7E 58 95 EA F2 67 24 35 BA D8 17 F5 45 A3 71 48"),
+ bk16, hex("")),
+ hex("EF 85 FB 89 0B B8 47 2F 4D AB 20 39 4D CA 78 1D\n" +
+ "AD 87 7E DA 39 D5 0C 87 0C 0D 5A 0A 8E 48 C7 18"));
+
+ check(enc(dk128, hex("7B CA 28 5E 2F D4 13 0F B5 5B 1A 5C 83 BC 5B 24"),
+ bk16, hex("00 01 02 03 04 05")),
+ hex("84 D7 F3 07 54 ED 98 7B AB 0B F3 50 6B EB 09 CF\n" +
+ "B5 54 02 CE F7 E6 87 7C E9 9E 24 7E 52 D1 6E D4\n" +
+ "42 1D FD F8 97 6C"));
+
+ check(enc(dk128, hex("56 AB 21 71 3F F6 2C 0A 14 57 20 0F 6F A9 94 8F"),
+ bk16, hex("00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F")),
+ hex("35 17 D6 40 F5 0D DC 8A D3 62 87 22 B3 56 9D 2A\n" +
+ "E0 74 93 FA 82 63 25 40 80 EA 65 C1 00 8E 8F C2\n" +
+ "95 FB 48 52 E7 D8 3E 1E 7C 48 C3 7E EB E6 B0 D3"));
+
+ check(enc(dk128, hex("A7 A4 E2 9A 47 28 CE 10 66 4F B6 4E 49 AD 3F AC"),
+ bk16, hex("00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n" +
+ "10 11 12 13 14")),
+ hex("72 0F 73 B1 8D 98 59 CD 6C CB 43 46 11 5C D3 36\n" +
+ "C7 0F 58 ED C0 C4 43 7C 55 73 54 4C 31 C8 13 BC\n" +
+ "E1 E6 D0 72 C1 86 B3 9A 41 3C 2F 92 CA 9B 83 34\n" +
+ "A2 87 FF CB FC\n"));
+
+ if (aes256ok) {
+ check(enc(dk256, hex("F7 64 E9 FA 15 C2 76 47 8B 2C 7D 0C 4E 5F 58 E4"),
+ bk32, hex("")),
+ hex("41 F5 3F A5 BF E7 02 6D 91 FA F9 BE 95 91 95 A0\n" +
+ "58 70 72 73 A9 6A 40 F0 A0 19 60 62 1A C6 12 74\n" +
+ "8B 9B BF BE 7E B4 CE 3C\n"));
+
+ check(enc(dk256, hex("B8 0D 32 51 C1 F6 47 14 94 25 6F FE 71 2D 0B 9A"),
+ bk32, hex("00 01 02 03 04 05")),
+ hex("4E D7 B3 7C 2B CA C8 F7 4F 23 C1 CF 07 E6 2B C7\n" +
+ "B7 5F B3 F6 37 B9 F5 59 C7 F6 64 F6 9E AB 7B 60\n" +
+ "92 23 75 26 EA 0D 1F 61 CB 20 D6 9D 10 F2\n"));
+
+ check(enc(dk256, hex("53 BF 8A 0D 10 52 65 D4 E2 76 42 86 24 CE 5E 63"),
+ bk32, hex("00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F")),
+ hex("BC 47 FF EC 79 98 EB 91 E8 11 5C F8 D1 9D AC 4B\n" +
+ "BB E2 E1 63 E8 7D D3 7F 49 BE CA 92 02 77 64 F6\n" +
+ "8C F5 1F 14 D7 98 C2 27 3F 35 DF 57 4D 1F 93 2E\n" +
+ "40 C4 FF 25 5B 36 A2 66\n"));
+
+ check(enc(dk256, hex("76 3E 65 36 7E 86 4F 02 F5 51 53 C7 E3 B5 8A F1"),
+ bk32, hex("00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n" +
+ "10 11 12 13 14")),
+ hex("40 01 3E 2D F5 8E 87 51 95 7D 28 78 BC D2 D6 FE\n" +
+ "10 1C CF D5 56 CB 1E AE 79 DB 3C 3E E8 64 29 F2\n" +
+ "B2 A6 02 AC 86 FE F6 EC B6 47 D6 29 5F AE 07 7A\n" +
+ "1F EB 51 75 08 D2 C1 6B 41 92 E0 1F 62\n"));
+ }
+
+ // Sample checksums:
+
+ byte[] msg = hex(
+ "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n" +
+ "10 11 12 13 14");
+
+ check(checksum(dk128, bk16, msg), hex(
+ "D7 83 67 18 66 43 D6 7B 41 1C BA 91 39 FC 1D EE"));
+
+ check(checksum(dk256, bk32, msg), hex(
+ "45 EE 79 15 67 EE FC A3 7F 4A C1 E0 22 2D E8 0D\n" +
+ "43 C3 BF A0 66 99 67 2A"));
+
+ // Sample pseudorandom function (PRF) invocations:
+ // Java does not support PRF. Skipped.
+ }
+
+ private static byte[] stringToKey(AesSha2DkCrypto dk,
+ char[] pass, byte[] salt, byte[] params) throws Exception {
+ Method m = AesSha2DkCrypto.class.getDeclaredMethod("stringToKey",
+ char[].class, byte[].class, byte[].class);
+ m.setAccessible(true);
+ return (byte[])m.invoke(dk, pass, salt, params);
+ }
+
+ private static byte[] deriveKey(AesSha2DkCrypto dk, byte[] baseKey,
+ int usage, byte type) throws Exception {
+ Method m = AesSha2DkCrypto.class.getDeclaredMethod("deriveKey",
+ byte[].class, int.class, byte.class);
+ m.setAccessible(true);
+ return (byte[]) m.invoke(dk, baseKey, usage, type);
+ }
+
+ private static byte[] cat(byte[] b1, byte[] b2) {
+ byte[] result = Arrays.copyOf(b1, b1.length + b2.length);
+ System.arraycopy(b2, 0, result, b1.length, b2.length);
+ return result;
+ }
+
+ private static byte[] enc(AesSha2DkCrypto dk, byte[] confounder,
+ byte[] bk, byte[] text) throws Exception {
+ return dk.encryptRaw(bk, 2, new byte[16], cat(confounder, text),
+ 0, confounder.length + text.length);
+ }
+
+ private static byte[] checksum(AesSha2DkCrypto dk, byte[] baseKey, byte[] text)
+ throws Exception {
+ return dk.calculateChecksum(baseKey, 2, text, 0, text.length);
+ }
+
+ private static byte[] hex(String var) {
+ var = var.replaceAll("\\s", "");
+ byte[] data = new byte[var.length()/2];
+ for (int i=0; i<data.length; i++) {
+ data[i] = Integer.valueOf(var.substring(2*i,2*i+2), 16).byteValue();
+ }
+ return data;
+ }
+
+ private static void check(byte[] b1, byte[] b2) throws Exception {
+ if (!Arrays.equals(b1, b2)) {
+ dump(b1); dump(b2);
+ throw new Exception("Failure");
+ }
+ }
+
+ private static void dump(byte[] data) throws Exception {
+ new HexDumpEncoder().encodeBuffer(data, System.err);
+ }
+}
--
2.19.1
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/gaoxiang90/openjdk-1.8.0.git
git@gitee.com:gaoxiang90/openjdk-1.8.0.git
gaoxiang90
openjdk-1.8.0
openjdk-1.8.0
master

搜索帮助