1/*
2 * Copyright (c) 2003, 2016, 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
26package sun.security.pkcs11;
27
28import java.io.IOException;
29import java.math.BigInteger;
30import java.nio.ByteBuffer;
31
32import java.security.*;
33import java.security.interfaces.*;
34import sun.nio.ch.DirectBuffer;
35
36import sun.security.util.*;
37import sun.security.x509.AlgorithmId;
38
39import sun.security.rsa.RSASignature;
40import sun.security.rsa.RSAPadding;
41
42import sun.security.pkcs11.wrapper.*;
43import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
44import sun.security.util.KeyUtil;
45
46/**
47 * Signature implementation class. This class currently supports the
48 * following algorithms:
49 *
50 * . DSA
51 *   . NONEwithDSA (RawDSA)
52 *   . SHA1withDSA
53 *   . NONEwithDSAinP1363Format (RawDSAinP1363Format)
54 *   . SHA1withDSAinP1363Format
55 * . RSA:
56 *   . MD2withRSA
57 *   . MD5withRSA
58 *   . SHA1withRSA
59 *   . SHA224withRSA
60 *   . SHA256withRSA
61 *   . SHA384withRSA
62 *   . SHA512withRSA
63 * . ECDSA
64 *   . NONEwithECDSA
65 *   . SHA1withECDSA
66 *   . SHA224withECDSA
67 *   . SHA256withECDSA
68 *   . SHA384withECDSA
69 *   . SHA512withECDSA
70 *   . NONEwithECDSAinP1363Format
71 *   . SHA1withECDSAinP1363Format
72 *   . SHA224withECDSAinP1363Format
73 *   . SHA256withECDSAinP1363Format
74 *   . SHA384withECDSAinP1363Format
75 *   . SHA512withECDSAinP1363Format
76 *
77 * Note that the underlying PKCS#11 token may support complete signature
78 * algorithm (e.g. CKM_DSA_SHA1, CKM_MD5_RSA_PKCS), or it may just
79 * implement the signature algorithm without hashing (e.g. CKM_DSA, CKM_PKCS),
80 * or it may only implement the raw public key operation (CKM_RSA_X_509).
81 * This class uses what is available and adds whatever extra processing
82 * is needed.
83 *
84 * @author  Andreas Sterbenz
85 * @since   1.5
86 */
87final class P11Signature extends SignatureSpi {
88
89    // token instance
90    private final Token token;
91
92    // algorithm name
93    private final String algorithm;
94
95    // name of the key algorithm, currently either RSA or DSA
96    private final String keyAlgorithm;
97
98    // mechanism id
99    private final long mechanism;
100
101    // digest algorithm OID, if we encode RSA signature ourselves
102    private final ObjectIdentifier digestOID;
103
104    // type, one of T_* below
105    private final int type;
106
107    // key instance used, if init*() was called
108    private P11Key p11Key;
109
110    // message digest, if we do the digesting ourselves
111    private final MessageDigest md;
112
113    // associated session, if any
114    private Session session;
115
116    // mode, one of M_* below
117    private int mode;
118
119    // flag indicating whether an operation is initialized
120    private boolean initialized;
121
122    // buffer, for update(byte) or DSA
123    private final byte[] buffer;
124
125    // total number of bytes processed in current operation
126    private int bytesProcessed;
127
128    // The format, to be used for DSA and ECDSA signatures.
129    // If true, the IEEE P1363 format will be used, the concatenation of
130    // r and s. If false (default), the signature will be formatted as a
131    // DER-encoded ASN.1 sequence of r and s.
132    private boolean p1363Format = false;
133
134    // constant for signing mode
135    private final static int M_SIGN   = 1;
136    // constant for verification mode
137    private final static int M_VERIFY = 2;
138
139    // constant for type digesting, we do the hashing ourselves
140    private final static int T_DIGEST = 1;
141    // constant for type update, token does everything
142    private final static int T_UPDATE = 2;
143    // constant for type raw, used with RawDSA and NONEwithECDSA only
144    private final static int T_RAW    = 3;
145
146    // XXX PKCS#11 v2.20 says "should not be longer than 1024 bits",
147    // but this is a little arbitrary
148    private final static int RAW_ECDSA_MAX = 128;
149
150    P11Signature(Token token, String algorithm, long mechanism)
151            throws NoSuchAlgorithmException, PKCS11Exception {
152        super();
153        this.token = token;
154        this.algorithm = algorithm;
155        this.mechanism = mechanism;
156        byte[] buffer = null;
157        ObjectIdentifier digestOID = null;
158        MessageDigest md = null;
159        switch ((int)mechanism) {
160        case (int)CKM_MD2_RSA_PKCS:
161        case (int)CKM_MD5_RSA_PKCS:
162        case (int)CKM_SHA1_RSA_PKCS:
163        case (int)CKM_SHA224_RSA_PKCS:
164        case (int)CKM_SHA256_RSA_PKCS:
165        case (int)CKM_SHA384_RSA_PKCS:
166        case (int)CKM_SHA512_RSA_PKCS:
167            keyAlgorithm = "RSA";
168            type = T_UPDATE;
169            buffer = new byte[1];
170            break;
171        case (int)CKM_DSA_SHA1:
172            keyAlgorithm = "DSA";
173            type = T_UPDATE;
174            buffer = new byte[1];
175            break;
176        case (int)CKM_ECDSA_SHA1:
177            keyAlgorithm = "EC";
178            type = T_UPDATE;
179            buffer = new byte[1];
180            break;
181        case (int)CKM_DSA:
182            keyAlgorithm = "DSA";
183            if (algorithm.equals("DSA") ||
184                algorithm.equals("DSAinP1363Format")) {
185                type = T_DIGEST;
186                md = MessageDigest.getInstance("SHA-1");
187            } else if (algorithm.equals("RawDSA") ||
188                       algorithm.equals("RawDSAinP1363Format")) {
189                type = T_RAW;
190                buffer = new byte[20];
191            } else {
192                throw new ProviderException(algorithm);
193            }
194            break;
195        case (int)CKM_ECDSA:
196            keyAlgorithm = "EC";
197            if (algorithm.equals("NONEwithECDSA") ||
198                algorithm.equals("NONEwithECDSAinP1363Format")) {
199                type = T_RAW;
200                buffer = new byte[RAW_ECDSA_MAX];
201            } else {
202                String digestAlg;
203                if (algorithm.equals("SHA1withECDSA") ||
204                    algorithm.equals("SHA1withECDSAinP1363Format")) {
205                    digestAlg = "SHA-1";
206                } else if (algorithm.equals("SHA224withECDSA") ||
207                           algorithm.equals("SHA224withECDSAinP1363Format")) {
208                    digestAlg = "SHA-224";
209                } else if (algorithm.equals("SHA256withECDSA") ||
210                           algorithm.equals("SHA256withECDSAinP1363Format")) {
211                    digestAlg = "SHA-256";
212                } else if (algorithm.equals("SHA384withECDSA") ||
213                           algorithm.equals("SHA384withECDSAinP1363Format")) {
214                    digestAlg = "SHA-384";
215                } else if (algorithm.equals("SHA512withECDSA") ||
216                           algorithm.equals("SHA512withECDSAinP1363Format")) {
217                    digestAlg = "SHA-512";
218                } else {
219                    throw new ProviderException(algorithm);
220                }
221                type = T_DIGEST;
222                md = MessageDigest.getInstance(digestAlg);
223            }
224            break;
225        case (int)CKM_RSA_PKCS:
226        case (int)CKM_RSA_X_509:
227            keyAlgorithm = "RSA";
228            type = T_DIGEST;
229            if (algorithm.equals("MD5withRSA")) {
230                md = MessageDigest.getInstance("MD5");
231                digestOID = AlgorithmId.MD5_oid;
232            } else if (algorithm.equals("SHA1withRSA")) {
233                md = MessageDigest.getInstance("SHA-1");
234                digestOID = AlgorithmId.SHA_oid;
235            } else if (algorithm.equals("MD2withRSA")) {
236                md = MessageDigest.getInstance("MD2");
237                digestOID = AlgorithmId.MD2_oid;
238            } else if (algorithm.equals("SHA224withRSA")) {
239                md = MessageDigest.getInstance("SHA-224");
240                digestOID = AlgorithmId.SHA224_oid;
241            } else if (algorithm.equals("SHA256withRSA")) {
242                md = MessageDigest.getInstance("SHA-256");
243                digestOID = AlgorithmId.SHA256_oid;
244            } else if (algorithm.equals("SHA384withRSA")) {
245                md = MessageDigest.getInstance("SHA-384");
246                digestOID = AlgorithmId.SHA384_oid;
247            } else if (algorithm.equals("SHA512withRSA")) {
248                md = MessageDigest.getInstance("SHA-512");
249                digestOID = AlgorithmId.SHA512_oid;
250            } else {
251                throw new ProviderException("Unknown signature: " + algorithm);
252            }
253            break;
254        default:
255            throw new ProviderException("Unknown mechanism: " + mechanism);
256        }
257        this.buffer = buffer;
258        this.digestOID = digestOID;
259        this.md = md;
260        if (algorithm.endsWith("inP1363Format")) {
261            this.p1363Format = true;
262        }
263    }
264
265    private void ensureInitialized() {
266        token.ensureValid();
267        if (initialized == false) {
268            initialize();
269        }
270    }
271
272    private void cancelOperation() {
273        token.ensureValid();
274        if (initialized == false) {
275            return;
276        }
277        initialized = false;
278        if ((session == null) || (token.explicitCancel == false)) {
279            return;
280        }
281        if (session.hasObjects() == false) {
282            session = token.killSession(session);
283            return;
284        }
285        // "cancel" operation by finishing it
286        // XXX make sure all this always works correctly
287        if (mode == M_SIGN) {
288            try {
289                if (type == T_UPDATE) {
290                    token.p11.C_SignFinal(session.id(), 0);
291                } else {
292                    byte[] digest;
293                    if (type == T_DIGEST) {
294                        digest = md.digest();
295                    } else { // T_RAW
296                        digest = buffer;
297                    }
298                    token.p11.C_Sign(session.id(), digest);
299                }
300            } catch (PKCS11Exception e) {
301                throw new ProviderException("cancel failed", e);
302            }
303        } else { // M_VERIFY
304            try {
305                byte[] signature;
306                if (keyAlgorithm.equals("DSA")) {
307                    signature = new byte[40];
308                } else {
309                    signature = new byte[(p11Key.length() + 7) >> 3];
310                }
311                if (type == T_UPDATE) {
312                    token.p11.C_VerifyFinal(session.id(), signature);
313                } else {
314                    byte[] digest;
315                    if (type == T_DIGEST) {
316                        digest = md.digest();
317                    } else { // T_RAW
318                        digest = buffer;
319                    }
320                    token.p11.C_Verify(session.id(), digest, signature);
321                }
322            } catch (PKCS11Exception e) {
323                // will fail since the signature is incorrect
324                // XXX check error code
325            }
326        }
327    }
328
329    // assumes current state is initialized == false
330    private void initialize() {
331        try {
332            if (session == null) {
333                session = token.getOpSession();
334            }
335            if (mode == M_SIGN) {
336                token.p11.C_SignInit(session.id(),
337                        new CK_MECHANISM(mechanism), p11Key.keyID);
338            } else {
339                token.p11.C_VerifyInit(session.id(),
340                        new CK_MECHANISM(mechanism), p11Key.keyID);
341            }
342            initialized = true;
343        } catch (PKCS11Exception e) {
344            throw new ProviderException("Initialization failed", e);
345        }
346        if (bytesProcessed != 0) {
347            bytesProcessed = 0;
348            if (md != null) {
349                md.reset();
350            }
351        }
352    }
353
354    private void checkKeySize(String keyAlgo, Key key)
355        throws InvalidKeyException {
356        CK_MECHANISM_INFO mechInfo = null;
357        try {
358            mechInfo = token.getMechanismInfo(mechanism);
359        } catch (PKCS11Exception e) {
360            // should not happen, ignore for now.
361        }
362        if (mechInfo == null) {
363            // skip the check if no native info available
364            return;
365        }
366        int minKeySize = (int) mechInfo.ulMinKeySize;
367        int maxKeySize = (int) mechInfo.ulMaxKeySize;
368        // need to override the MAX keysize for SHA1withDSA
369        if (md != null && mechanism == CKM_DSA && maxKeySize > 1024) {
370               maxKeySize = 1024;
371        }
372        int keySize = 0;
373        if (key instanceof P11Key) {
374            keySize = ((P11Key) key).length();
375        } else {
376            if (keyAlgo.equals("RSA")) {
377                keySize = ((RSAKey) key).getModulus().bitLength();
378            } else if (keyAlgo.equals("DSA")) {
379                keySize = ((DSAKey) key).getParams().getP().bitLength();
380            } else if (keyAlgo.equals("EC")) {
381                keySize = ((ECKey) key).getParams().getCurve().getField().getFieldSize();
382            } else {
383                throw new ProviderException("Error: unsupported algo " + keyAlgo);
384            }
385        }
386        if ((minKeySize != -1) && (keySize < minKeySize)) {
387            throw new InvalidKeyException(keyAlgo +
388                " key must be at least " + minKeySize + " bits");
389        }
390        if ((maxKeySize != -1) && (keySize > maxKeySize)) {
391            throw new InvalidKeyException(keyAlgo +
392                " key must be at most " + maxKeySize + " bits");
393        }
394        if (keyAlgo.equals("RSA")) {
395            checkRSAKeyLength(keySize);
396        }
397    }
398
399    private void checkRSAKeyLength(int len) throws InvalidKeyException {
400        RSAPadding padding;
401        try {
402            padding = RSAPadding.getInstance
403                (RSAPadding.PAD_BLOCKTYPE_1, (len + 7) >> 3);
404        } catch (InvalidAlgorithmParameterException iape) {
405            throw new InvalidKeyException(iape.getMessage());
406        }
407        int maxDataSize = padding.getMaxDataSize();
408        int encodedLength;
409        if (algorithm.equals("MD5withRSA") ||
410            algorithm.equals("MD2withRSA")) {
411            encodedLength = 34;
412        } else if (algorithm.equals("SHA1withRSA")) {
413            encodedLength = 35;
414        } else if (algorithm.equals("SHA224withRSA")) {
415            encodedLength = 47;
416        } else if (algorithm.equals("SHA256withRSA")) {
417            encodedLength = 51;
418        } else if (algorithm.equals("SHA384withRSA")) {
419            encodedLength = 67;
420        } else if (algorithm.equals("SHA512withRSA")) {
421            encodedLength = 83;
422        } else {
423            throw new ProviderException("Unknown signature algo: " + algorithm);
424        }
425        if (encodedLength > maxDataSize) {
426            throw new InvalidKeyException
427                ("Key is too short for this signature algorithm");
428        }
429    }
430
431    // see JCA spec
432    protected void engineInitVerify(PublicKey publicKey)
433            throws InvalidKeyException {
434        if (publicKey == null) {
435            throw new InvalidKeyException("Key must not be null");
436        }
437        // Need to check key length whenever a new key is set
438        if (publicKey != p11Key) {
439            checkKeySize(keyAlgorithm, publicKey);
440        }
441        cancelOperation();
442        mode = M_VERIFY;
443        p11Key = P11KeyFactory.convertKey(token, publicKey, keyAlgorithm);
444        initialize();
445    }
446
447    // see JCA spec
448    protected void engineInitSign(PrivateKey privateKey)
449            throws InvalidKeyException {
450        if (privateKey == null) {
451            throw new InvalidKeyException("Key must not be null");
452        }
453        // Need to check RSA key length whenever a new key is set
454        if (privateKey != p11Key) {
455            checkKeySize(keyAlgorithm, privateKey);
456        }
457        cancelOperation();
458        mode = M_SIGN;
459        p11Key = P11KeyFactory.convertKey(token, privateKey, keyAlgorithm);
460        initialize();
461    }
462
463    // see JCA spec
464    protected void engineUpdate(byte b) throws SignatureException {
465        ensureInitialized();
466        switch (type) {
467        case T_UPDATE:
468            buffer[0] = b;
469            engineUpdate(buffer, 0, 1);
470            break;
471        case T_DIGEST:
472            md.update(b);
473            bytesProcessed++;
474            break;
475        case T_RAW:
476            if (bytesProcessed >= buffer.length) {
477                bytesProcessed = buffer.length + 1;
478                return;
479            }
480            buffer[bytesProcessed++] = b;
481            break;
482        default:
483            throw new ProviderException("Internal error");
484        }
485    }
486
487    // see JCA spec
488    protected void engineUpdate(byte[] b, int ofs, int len)
489            throws SignatureException {
490        ensureInitialized();
491        if (len == 0) {
492            return;
493        }
494        switch (type) {
495        case T_UPDATE:
496            try {
497                if (mode == M_SIGN) {
498                    token.p11.C_SignUpdate(session.id(), 0, b, ofs, len);
499                } else {
500                    token.p11.C_VerifyUpdate(session.id(), 0, b, ofs, len);
501                }
502                bytesProcessed += len;
503            } catch (PKCS11Exception e) {
504                throw new ProviderException(e);
505            }
506            break;
507        case T_DIGEST:
508            md.update(b, ofs, len);
509            bytesProcessed += len;
510            break;
511        case T_RAW:
512            if (bytesProcessed + len > buffer.length) {
513                bytesProcessed = buffer.length + 1;
514                return;
515            }
516            System.arraycopy(b, ofs, buffer, bytesProcessed, len);
517            bytesProcessed += len;
518            break;
519        default:
520            throw new ProviderException("Internal error");
521        }
522    }
523
524    // see JCA spec
525    protected void engineUpdate(ByteBuffer byteBuffer) {
526        ensureInitialized();
527        int len = byteBuffer.remaining();
528        if (len <= 0) {
529            return;
530        }
531        switch (type) {
532        case T_UPDATE:
533            if (byteBuffer instanceof DirectBuffer == false) {
534                // cannot do better than default impl
535                super.engineUpdate(byteBuffer);
536                return;
537            }
538            long addr = ((DirectBuffer)byteBuffer).address();
539            int ofs = byteBuffer.position();
540            try {
541                if (mode == M_SIGN) {
542                    token.p11.C_SignUpdate
543                        (session.id(), addr + ofs, null, 0, len);
544                } else {
545                    token.p11.C_VerifyUpdate
546                        (session.id(), addr + ofs, null, 0, len);
547                }
548                bytesProcessed += len;
549                byteBuffer.position(ofs + len);
550            } catch (PKCS11Exception e) {
551                throw new ProviderException("Update failed", e);
552            }
553            break;
554        case T_DIGEST:
555            md.update(byteBuffer);
556            bytesProcessed += len;
557            break;
558        case T_RAW:
559            if (bytesProcessed + len > buffer.length) {
560                bytesProcessed = buffer.length + 1;
561                return;
562            }
563            byteBuffer.get(buffer, bytesProcessed, len);
564            bytesProcessed += len;
565            break;
566        default:
567            throw new ProviderException("Internal error");
568        }
569    }
570
571    // see JCA spec
572    protected byte[] engineSign() throws SignatureException {
573        ensureInitialized();
574        try {
575            byte[] signature;
576            if (type == T_UPDATE) {
577                int len = keyAlgorithm.equals("DSA") ? 40 : 0;
578                signature = token.p11.C_SignFinal(session.id(), len);
579            } else {
580                byte[] digest;
581                if (type == T_DIGEST) {
582                    digest = md.digest();
583                } else { // T_RAW
584                    if (mechanism == CKM_DSA) {
585                        if (bytesProcessed != buffer.length) {
586                            throw new SignatureException
587                            ("Data for RawDSA must be exactly 20 bytes long");
588                        }
589                        digest = buffer;
590                    } else { // CKM_ECDSA
591                        if (bytesProcessed > buffer.length) {
592                            throw new SignatureException("Data for NONEwithECDSA"
593                            + " must be at most " + RAW_ECDSA_MAX + " bytes long");
594                        }
595                        digest = new byte[bytesProcessed];
596                        System.arraycopy(buffer, 0, digest, 0, bytesProcessed);
597                    }
598                }
599                if (keyAlgorithm.equals("RSA") == false) {
600                    // DSA and ECDSA
601                    signature = token.p11.C_Sign(session.id(), digest);
602                } else { // RSA
603                    byte[] data = encodeSignature(digest);
604                    if (mechanism == CKM_RSA_X_509) {
605                        data = pkcs1Pad(data);
606                    }
607                    signature = token.p11.C_Sign(session.id(), data);
608                }
609            }
610            if (keyAlgorithm.equals("RSA")) {
611                return signature;
612            } else {
613                if (p1363Format) {
614                    return signature;
615                } else {
616                    return dsaToASN1(signature);
617                }
618            }
619        } catch (PKCS11Exception pe) {
620            throw new ProviderException(pe);
621        } catch (SignatureException | ProviderException e) {
622            cancelOperation();
623            throw e;
624        } finally {
625            initialized = false;
626            session = token.releaseSession(session);
627        }
628    }
629
630    // see JCA spec
631    protected boolean engineVerify(byte[] signature) throws SignatureException {
632        ensureInitialized();
633        try {
634            if (!p1363Format) {
635                if (keyAlgorithm.equals("DSA")) {
636                    signature = asn1ToDSA(signature);
637                } else if (keyAlgorithm.equals("EC")) {
638                    signature = asn1ToECDSA(signature);
639                }
640            }
641            if (type == T_UPDATE) {
642                token.p11.C_VerifyFinal(session.id(), signature);
643            } else {
644                byte[] digest;
645                if (type == T_DIGEST) {
646                    digest = md.digest();
647                } else { // T_RAW
648                    if (mechanism == CKM_DSA) {
649                        if (bytesProcessed != buffer.length) {
650                            throw new SignatureException
651                            ("Data for RawDSA must be exactly 20 bytes long");
652                        }
653                        digest = buffer;
654                    } else {
655                        if (bytesProcessed > buffer.length) {
656                            throw new SignatureException("Data for NONEwithECDSA"
657                            + " must be at most " + RAW_ECDSA_MAX + " bytes long");
658                        }
659                        digest = new byte[bytesProcessed];
660                        System.arraycopy(buffer, 0, digest, 0, bytesProcessed);
661                    }
662                }
663                if (keyAlgorithm.equals("RSA") == false) {
664                    // DSA and ECDSA
665                    token.p11.C_Verify(session.id(), digest, signature);
666                } else { // RSA
667                    byte[] data = encodeSignature(digest);
668                    if (mechanism == CKM_RSA_X_509) {
669                        data = pkcs1Pad(data);
670                    }
671                    token.p11.C_Verify(session.id(), data, signature);
672                }
673            }
674            return true;
675        } catch (PKCS11Exception pe) {
676            long errorCode = pe.getErrorCode();
677            if (errorCode == CKR_SIGNATURE_INVALID) {
678                return false;
679            }
680            if (errorCode == CKR_SIGNATURE_LEN_RANGE) {
681                // return false rather than throwing an exception
682                return false;
683            }
684            // ECF bug?
685            if (errorCode == CKR_DATA_LEN_RANGE) {
686                return false;
687            }
688            throw new ProviderException(pe);
689        }  catch (SignatureException | ProviderException e) {
690            cancelOperation();
691            throw e;
692        } finally {
693            initialized = false;
694            session = token.releaseSession(session);
695        }
696    }
697
698    private byte[] pkcs1Pad(byte[] data) {
699        try {
700            int len = (p11Key.length() + 7) >> 3;
701            RSAPadding padding = RSAPadding.getInstance
702                                        (RSAPadding.PAD_BLOCKTYPE_1, len);
703            byte[] padded = padding.pad(data);
704            return padded;
705        } catch (GeneralSecurityException e) {
706            throw new ProviderException(e);
707        }
708    }
709
710    private byte[] encodeSignature(byte[] digest) throws SignatureException {
711        try {
712            return RSASignature.encodeSignature(digestOID, digest);
713        } catch (IOException e) {
714            throw new SignatureException("Invalid encoding", e);
715        }
716    }
717
718//    private static byte[] decodeSignature(byte[] signature) throws IOException {
719//      return RSASignature.decodeSignature(digestOID, signature);
720//    }
721
722    // For DSA and ECDSA signatures, PKCS#11 represents them as a simple
723    // byte array that contains the concatenation of r and s.
724    // For DSA, r and s are always exactly 20 bytes long.
725    // For ECDSA, r and s are of variable length, but we know that each
726    // occupies half of the array.
727    private static byte[] dsaToASN1(byte[] signature) {
728        int n = signature.length >> 1;
729        BigInteger r = new BigInteger(1, P11Util.subarray(signature, 0, n));
730        BigInteger s = new BigInteger(1, P11Util.subarray(signature, n, n));
731        try {
732            DerOutputStream outseq = new DerOutputStream(100);
733            outseq.putInteger(r);
734            outseq.putInteger(s);
735            DerValue result = new DerValue(DerValue.tag_Sequence,
736                                           outseq.toByteArray());
737            return result.toByteArray();
738        } catch (java.io.IOException e) {
739            throw new RuntimeException("Internal error", e);
740        }
741    }
742
743    private static byte[] asn1ToDSA(byte[] sig) throws SignatureException {
744        try {
745            // Enforce strict DER checking for signatures
746            DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
747            DerValue[] values = in.getSequence(2);
748
749            // check number of components in the read sequence
750            // and trailing data
751            if ((values.length != 2) || (in.available() != 0)) {
752                throw new IOException("Invalid encoding for signature");
753            }
754
755            BigInteger r = values[0].getPositiveBigInteger();
756            BigInteger s = values[1].getPositiveBigInteger();
757
758            byte[] br = toByteArray(r, 20);
759            byte[] bs = toByteArray(s, 20);
760            if ((br == null) || (bs == null)) {
761                throw new SignatureException("Out of range value for R or S");
762            }
763            return P11Util.concat(br, bs);
764        } catch (SignatureException e) {
765            throw e;
766        } catch (Exception e) {
767            throw new SignatureException("Invalid encoding for signature", e);
768        }
769    }
770
771    private byte[] asn1ToECDSA(byte[] sig) throws SignatureException {
772        try {
773            // Enforce strict DER checking for signatures
774            DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
775            DerValue[] values = in.getSequence(2);
776
777            // check number of components in the read sequence
778            // and trailing data
779            if ((values.length != 2) || (in.available() != 0)) {
780                throw new IOException("Invalid encoding for signature");
781            }
782
783            BigInteger r = values[0].getPositiveBigInteger();
784            BigInteger s = values[1].getPositiveBigInteger();
785
786            // trim leading zeroes
787            byte[] br = KeyUtil.trimZeroes(r.toByteArray());
788            byte[] bs = KeyUtil.trimZeroes(s.toByteArray());
789            int k = Math.max(br.length, bs.length);
790            // r and s each occupy half the array
791            byte[] res = new byte[k << 1];
792            System.arraycopy(br, 0, res, k - br.length, br.length);
793            System.arraycopy(bs, 0, res, res.length - bs.length, bs.length);
794            return res;
795        } catch (Exception e) {
796            throw new SignatureException("Invalid encoding for signature", e);
797        }
798    }
799
800    private static byte[] toByteArray(BigInteger bi, int len) {
801        byte[] b = bi.toByteArray();
802        int n = b.length;
803        if (n == len) {
804            return b;
805        }
806        if ((n == len + 1) && (b[0] == 0)) {
807            byte[] t = new byte[len];
808            System.arraycopy(b, 1, t, 0, len);
809            return t;
810        }
811        if (n > len) {
812            return null;
813        }
814        // must be smaller
815        byte[] t = new byte[len];
816        System.arraycopy(b, 0, t, (len - n), n);
817        return t;
818    }
819
820    // see JCA spec
821    @SuppressWarnings("deprecation")
822    protected void engineSetParameter(String param, Object value)
823            throws InvalidParameterException {
824        throw new UnsupportedOperationException("setParameter() not supported");
825    }
826
827    // see JCA spec
828    @SuppressWarnings("deprecation")
829    protected Object engineGetParameter(String param)
830            throws InvalidParameterException {
831        throw new UnsupportedOperationException("getParameter() not supported");
832    }
833}
834