History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/pkcs11/P11SecureRandom.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/pkcs11/P11SecureRandom.java+200−0
@@ -0,0 +1,200 @@
1+/*
2+ * Copyright (c) 2003, 2010, 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.pkcs11;
27+
28+import java.util.*;
29+import java.io.*;
30+import java.security.*;
31+
32+import sun.security.pkcs11.wrapper.*;
33+import sun.security.pkcs11.wrapper.PKCS11Constants.*;
34+
35+/**
36+ * SecureRandom implementation class. Some tokens support only
37+ * C_GenerateRandom() and not C_SeedRandom(). In order not to lose an
38+ * application specified seed, we create a SHA1PRNG that we mix with in that
39+ * case.
40+ *
41+ * Note that since SecureRandom is thread safe, we only need one
42+ * instance per PKCS#11 token instance. It is created on demand and cached
43+ * in the SunPKCS11 class.
44+ *
45+ * Also note that we obtain the PKCS#11 session on demand, no need to tie one
46+ * up.
47+ *
48+ * @author Andreas Sterbenz
49+ * @since 1.5
50+ */
51+final class P11SecureRandom extends SecureRandomSpi {
52+
53+ private static final long serialVersionUID = -8939510236124553291L;
54+
55+ // token instance
56+ private final Token token;
57+
58+ // PRNG for mixing, non-null if active (i.e. setSeed() has been called)
59+ private volatile SecureRandom mixRandom;
60+
61+ // buffer, if mixing is used
62+ private byte[] mixBuffer;
63+
64+ // bytes remaining in mixBuffer, if mixing is used
65+ private int buffered;
66+
67+ /*
68+ * we buffer data internally for efficiency but limit the lifetime
69+ * to avoid using stale bits.
70+ */
71+ // lifetime in ms, currently 100 ms (0.1 s)
72+ private static final long MAX_IBUFFER_TIME = 100;
73+
74+ // size of the internal buffer
75+ private static final int IBUFFER_SIZE = 32;
76+
77+ // internal buffer for the random bits
78+ private transient byte[] iBuffer = new byte[IBUFFER_SIZE];
79+
80+ // number of bytes remain in iBuffer
81+ private transient int ibuffered = 0;
82+
83+ // time that data was read into iBuffer
84+ private transient long lastRead = 0L;
85+
86+ P11SecureRandom(Token token) {
87+ this.token = token;
88+ }
89+
90+ // see JCA spec
91+ protected synchronized void engineSetSeed(byte[] seed) {
92+ if (seed == null) {
93+ throw new NullPointerException("seed must not be null");
94+ }
95+ Session session = null;
96+ try {
97+ session = token.getOpSession();
98+ token.p11.C_SeedRandom(session.id(), seed);
99+ } catch (PKCS11Exception e) {
100+ // cannot set seed
101+ // let a SHA1PRNG use that seed instead
102+ SecureRandom random = mixRandom;
103+ if (random != null) {
104+ random.setSeed(seed);
105+ } else {
106+ try {
107+ mixBuffer = new byte[20];
108+ random = SecureRandom.getInstance("SHA1PRNG");
109+ // initialize object before assigning to class field
110+ random.setSeed(seed);
111+ mixRandom = random;
112+ } catch (NoSuchAlgorithmException ee) {
113+ throw new ProviderException(ee);
114+ }
115+ }
116+ } finally {
117+ token.releaseSession(session);
118+ }
119+ }
120+
121+ // see JCA spec
122+ protected void engineNextBytes(byte[] bytes) {
123+ if ((bytes == null) || (bytes.length == 0)) {
124+ return;
125+ }
126+ if (bytes.length <= IBUFFER_SIZE) {
127+ int ofs = 0;
128+ synchronized (iBuffer) {
129+ while (ofs < bytes.length) {
130+ long time = System.currentTimeMillis();
131+ // refill the internal buffer if empty or stale
132+ if ((ibuffered == 0) ||
133+ !(time - lastRead < MAX_IBUFFER_TIME)) {
134+ lastRead = time;
135+ implNextBytes(iBuffer);
136+ ibuffered = IBUFFER_SIZE;
137+ }
138+ // copy the buffered bytes into 'bytes'
139+ while ((ofs < bytes.length) && (ibuffered > 0)) {
140+ bytes[ofs++] = iBuffer[IBUFFER_SIZE - ibuffered--];
141+ }
142+ }
143+ }
144+ } else {
145+ // avoid using the buffer - just fill bytes directly
146+ implNextBytes(bytes);
147+ }
148+
149+ }
150+
151+ // see JCA spec
152+ protected byte[] engineGenerateSeed(int numBytes) {
153+ byte[] b = new byte[numBytes];
154+ engineNextBytes(b);
155+ return b;
156+ }
157+
158+ private void mix(byte[] b) {
159+ SecureRandom random = mixRandom;
160+ if (random == null) {
161+ // avoid mixing if setSeed() has never been called
162+ return;
163+ }
164+ synchronized (this) {
165+ int ofs = 0;
166+ int len = b.length;
167+ while (len-- > 0) {
168+ if (buffered == 0) {
169+ random.nextBytes(mixBuffer);
170+ buffered = mixBuffer.length;
171+ }
172+ b[ofs++] ^= mixBuffer[mixBuffer.length - buffered];
173+ buffered--;
174+ }
175+ }
176+ }
177+
178+ // fill up the specified buffer with random bytes, and mix them
179+ private void implNextBytes(byte[] bytes) {
180+ Session session = null;
181+ try {
182+ session = token.getOpSession();
183+ token.p11.C_GenerateRandom(session.id(), bytes);
184+ mix(bytes);
185+ } catch (PKCS11Exception e) {
186+ throw new ProviderException("nextBytes() failed", e);
187+ } finally {
188+ token.releaseSession(session);
189+ }
190+ }
191+
192+ private void readObject(ObjectInputStream in)
193+ throws IOException, ClassNotFoundException {
194+ in.defaultReadObject();
195+ // assign default values to non-null transient fields
196+ iBuffer = new byte[IBUFFER_SIZE];
197+ ibuffered = 0;
198+ lastRead = 0L;
199+ }
200+}