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