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