11/*
2- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
2626package com .sun .crypto .provider ;
2727
2828import sun .security .jca .JCAUtil ;
29+ import sun .security .pkcs .NamedPKCS8Key ;
2930import sun .security .provider .NamedKEM ;
3031import sun .security .provider .NamedKeyFactory ;
3132import sun .security .provider .NamedKeyPairGenerator ;
33+ import sun .security .util .KeyChoices ;
34+ import sun .security .x509 .NamedX509Key ;
3235
3336import java .security .*;
3437import java .util .Arrays ;
3740
3841public final class ML_KEM_Impls {
3942
43+ private static final int SEED_LEN = 64 ;
44+
45+ public static byte [] seedToExpanded (String pname , byte [] seed ) {
46+ return new ML_KEM (pname ).generateKemKeyPair (seed )
47+ .decapsulationKey ()
48+ .keyBytes ();
49+ }
50+
51+ public static NamedX509Key privKeyToPubKey (NamedPKCS8Key npk ) {
52+ return new NamedX509Key (npk .getAlgorithm (),
53+ npk .getParams ().getName (),
54+ new ML_KEM (npk .getParams ().getName ()).privKeyToPubKey (npk .getExpanded ()));
55+ }
56+
4057 public sealed static class KPG
4158 extends NamedKeyPairGenerator permits KPG2 , KPG3 , KPG5 {
4259
@@ -50,25 +67,27 @@ protected KPG(String pname) {
5067 }
5168
5269 @ Override
53- protected byte [][] implGenerateKeyPair (String name , SecureRandom random ) {
54- byte [] seed = new byte [32 ];
70+ protected byte [][] implGenerateKeyPair (String pname , SecureRandom random ) {
71+ byte [] seed = new byte [SEED_LEN ];
5572 var r = random != null ? random : JCAUtil .getDefSecureRandom ();
5673 r .nextBytes (seed );
57- byte [] z = new byte [32 ];
58- r .nextBytes (z );
5974
60- ML_KEM mlKem = new ML_KEM (name );
75+ ML_KEM mlKem = new ML_KEM (pname );
6176 ML_KEM .ML_KEM_KeyPair kp ;
77+ kp = mlKem .generateKemKeyPair (seed );
78+ var expanded = kp .decapsulationKey ().keyBytes ();
79+
6280 try {
63- kp = mlKem .generateKemKeyPair (seed , z );
81+ return new byte [][]{
82+ kp .encapsulationKey ().keyBytes (),
83+ KeyChoices .writeToChoice (
84+ KeyChoices .getPreferred ("mlkem" ),
85+ seed , expanded ),
86+ expanded
87+ };
6488 } finally {
65- Arrays .fill (seed , (byte )0 );
66- Arrays .fill (z , (byte )0 );
89+ Arrays .fill (seed , (byte ) 0 );
6790 }
68- return new byte [][] {
69- kp .encapsulationKey ().keyBytes (),
70- kp .decapsulationKey ().keyBytes ()
71- };
7291 }
7392 }
7493
@@ -94,8 +113,39 @@ public sealed static class KF extends NamedKeyFactory permits KF2, KF3, KF5 {
94113 public KF () {
95114 super ("ML-KEM" , "ML-KEM-512" , "ML-KEM-768" , "ML-KEM-1024" );
96115 }
97- public KF (String name ) {
98- super ("ML-KEM" , name );
116+ public KF (String pname ) {
117+ super ("ML-KEM" , pname );
118+ }
119+
120+ @ Override
121+ protected byte [] implExpand (String pname , byte [] input )
122+ throws InvalidKeyException {
123+ return KeyChoices .choiceToExpanded (pname , SEED_LEN , input ,
124+ ML_KEM_Impls ::seedToExpanded );
125+ }
126+
127+ @ Override
128+ protected Key engineTranslateKey (Key key ) throws InvalidKeyException {
129+ var nk = toNamedKey (key );
130+ if (nk instanceof NamedPKCS8Key npk ) {
131+ var type = KeyChoices .getPreferred ("mlkem" );
132+ if (KeyChoices .typeOfChoice (npk .getRawBytes ()) != type ) {
133+ var encoding = KeyChoices .choiceToChoice (
134+ type ,
135+ npk .getParams ().getName (),
136+ SEED_LEN , npk .getRawBytes (),
137+ ML_KEM_Impls ::seedToExpanded );
138+ nk = NamedPKCS8Key .internalCreate (
139+ npk .getAlgorithm (),
140+ npk .getParams ().getName (),
141+ encoding ,
142+ npk .getExpanded ().clone ());
143+ if (npk != key ) { // npk is neither input or output
144+ npk .destroy ();
145+ }
146+ }
147+ }
148+ return nk ;
99149 }
100150 }
101151
@@ -121,15 +171,15 @@ public sealed static class K extends NamedKEM permits K2, K3, K5 {
121171 private static final int SEED_SIZE = 32 ;
122172
123173 @ Override
124- protected byte [][] implEncapsulate (String name , byte [] encapsulationKey ,
174+ protected byte [][] implEncapsulate (String pname , byte [] encapsulationKey ,
125175 Object ek , SecureRandom secureRandom ) {
126176
127177 byte [] randomBytes = new byte [SEED_SIZE ];
128178 var r = secureRandom != null ? secureRandom : JCAUtil .getDefSecureRandom ();
129179 r .nextBytes (randomBytes );
130180
131- ML_KEM mlKem = new ML_KEM (name );
132- ML_KEM .ML_KEM_EncapsulateResult mlKemEncapsulateResult = null ;
181+ ML_KEM mlKem = new ML_KEM (pname );
182+ ML_KEM .ML_KEM_EncapsulateResult mlKemEncapsulateResult ;
133183 try {
134184 mlKemEncapsulateResult = mlKem .encapsulate (
135185 new ML_KEM .ML_KEM_EncapsulationKey (
@@ -145,49 +195,49 @@ protected byte[][] implEncapsulate(String name, byte[] encapsulationKey,
145195 }
146196
147197 @ Override
148- protected byte [] implDecapsulate (String name , byte [] decapsulationKey ,
198+ protected byte [] implDecapsulate (String pname , byte [] decapsulationKey ,
149199 Object dk , byte [] cipherText )
150200 throws DecapsulateException {
151201
152- ML_KEM mlKem = new ML_KEM (name );
202+ ML_KEM mlKem = new ML_KEM (pname );
153203 var kpkeCipherText = new ML_KEM .K_PKE_CipherText (cipherText );
154204 return mlKem .decapsulate (new ML_KEM .ML_KEM_DecapsulationKey (
155205 decapsulationKey ), kpkeCipherText );
156206 }
157207
158208 @ Override
159- protected int implSecretSize (String name ) {
209+ protected int implSecretSize (String pname ) {
160210 return ML_KEM .SECRET_SIZE ;
161211 }
162212
163213 @ Override
164- protected int implEncapsulationSize (String name ) {
165- ML_KEM mlKem = new ML_KEM (name );
214+ protected int implEncapsulationSize (String pname ) {
215+ ML_KEM mlKem = new ML_KEM (pname );
166216 return mlKem .getEncapsulationSize ();
167217 }
168218
169219 @ Override
170- protected Object implCheckPublicKey (String name , byte [] pk )
220+ protected Object implCheckPublicKey (String pname , byte [] pk )
171221 throws InvalidKeyException {
172222
173- ML_KEM mlKem = new ML_KEM (name );
223+ ML_KEM mlKem = new ML_KEM (pname );
174224 return mlKem .checkPublicKey (pk );
175225 }
176226
177227 @ Override
178- protected Object implCheckPrivateKey (String name , byte [] sk )
228+ protected Object implCheckPrivateKey (String pname , byte [] sk )
179229 throws InvalidKeyException {
180230
181- ML_KEM mlKem = new ML_KEM (name );
231+ ML_KEM mlKem = new ML_KEM (pname );
182232 return mlKem .checkPrivateKey (sk );
183233 }
184234
185235 public K () {
186- super ("ML-KEM" , "ML-KEM-512" , "ML-KEM-768" , "ML-KEM-1024" );
236+ super ("ML-KEM" , new KF () );
187237 }
188238
189- public K (String name ) {
190- super ("ML-KEM" , name );
239+ public K (String pname ) {
240+ super ("ML-KEM" , new KF ( pname ) );
191241 }
192242 }
193243
0 commit comments