1 /* 2 * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.mscapi; 27 28 import sun.security.util.KeyUtil; 29 import sun.security.util.Length; 30 31 import java.math.BigInteger; 32 import java.security.Key; 33 import java.security.interfaces.ECPrivateKey; 34 import java.security.interfaces.ECPublicKey; 35 36 /** 37 * The handle for a key using the Microsoft Crypto API. 38 * 39 * @see CPrivateKey 40 * @see CPublicKey 41 * 42 * @since 1.6 43 * @author Stanley Man-Kit Ho 44 */ 45 abstract class CKey implements Key, Length { 46 private static final long serialVersionUID = -1088859394025049194L; 47 48 static class NativeHandles { 49 50 long hCryptProv = 0; 51 long hCryptKey = 0; 52 NativeHandles(long hCryptProv, long hCryptKey)53 public NativeHandles(long hCryptProv, long hCryptKey) { 54 this.hCryptProv = hCryptProv; 55 this.hCryptKey = hCryptKey; 56 } 57 58 @SuppressWarnings("deprecation") finalize()59 protected void finalize() throws Throwable { 60 try { 61 synchronized(this) { 62 cleanUp(hCryptProv, hCryptKey); 63 hCryptProv = 0; 64 hCryptKey = 0; 65 } 66 } finally { 67 super.finalize(); 68 } 69 } 70 } 71 72 protected final NativeHandles handles; 73 74 protected final int keyLength; 75 76 protected final String algorithm; 77 CKey(String algorithm, NativeHandles handles, int keyLength)78 protected CKey(String algorithm, NativeHandles handles, int keyLength) { 79 this.algorithm = algorithm; 80 this.handles = handles; 81 this.keyLength = keyLength; 82 } 83 84 // Native method to cleanup the key handle. cleanUp(long hCryptProv, long hCryptKey)85 private native static void cleanUp(long hCryptProv, long hCryptKey); 86 87 @Override length()88 public int length() { 89 return keyLength; 90 } 91 getHCryptKey()92 public long getHCryptKey() { 93 return handles.hCryptKey; 94 } 95 getHCryptProvider()96 public long getHCryptProvider() { 97 return handles.hCryptProv; 98 } 99 getAlgorithm()100 public String getAlgorithm() { 101 return algorithm; 102 } 103 getContainerName(long hCryptProv)104 protected native static String getContainerName(long hCryptProv); 105 getKeyType(long hCryptKey)106 protected native static String getKeyType(long hCryptKey); 107 108 // This java method generates EC BLOBs for public key or private key. 109 // See https://docs.microsoft.com/en-us/windows/desktop/api/bcrypt/ns-bcrypt-_bcrypt_ecckey_blob generateECBlob(Key k)110 static byte[] generateECBlob(Key k) { 111 112 int keyBitLength = KeyUtil.getKeySize(k); 113 int keyLen = (keyBitLength + 7) / 8; 114 boolean isPrivate = k instanceof ECPrivateKey; 115 116 byte[] keyBlob = new byte[8 + keyLen * (isPrivate ? 3 : 2)]; 117 keyBlob[0] = 'E'; 118 keyBlob[1] = 'C'; 119 keyBlob[2] = 'S'; 120 if (isPrivate) { 121 keyBlob[3] = (byte) (keyBitLength == 256 ? '2' 122 : (keyBitLength == 384 ? '4' : '6')); 123 } else { 124 keyBlob[3] = (byte) (keyBitLength == 256 ? '1' 125 : (keyBitLength == 384 ? '3' : '5')); 126 } 127 BigInteger x; 128 BigInteger y; 129 // Fill the array in reverse order (s -> y -> x -> len) in case 130 // one BigInteger encoding has an extra 0 at the beginning 131 if (isPrivate) { 132 // We can keep X and Y zero and it still works 133 ECPrivateKey prk = (ECPrivateKey)k; 134 BigInteger s = prk.getS(); 135 byte[] bs = s.toByteArray(); 136 System.arraycopy( 137 bs, 0, 138 keyBlob, 8 + keyLen + keyLen + keyLen - bs.length, 139 bs.length); 140 } else { 141 ECPublicKey puk = (ECPublicKey)k; 142 x = puk.getW().getAffineX(); 143 y = puk.getW().getAffineY(); 144 byte[] by = y.toByteArray(); 145 System.arraycopy(by, 0, keyBlob, 8 + keyLen + keyLen - by.length, 146 by.length); 147 byte[] bx = x.toByteArray(); 148 System.arraycopy(bx, 0, keyBlob, 8 + keyLen - bx.length, bx.length); 149 } 150 keyBlob[4] = (byte) keyLen; 151 keyBlob[5] = keyBlob[6] = keyBlob[7] = 0; 152 return keyBlob; 153 } 154 } 155