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 }