Path: blob/master/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java
41154 views
/*1* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.pkcs11;2627import java.io.IOException;28import java.math.BigInteger;29import java.nio.ByteBuffer;3031import java.security.*;32import java.security.interfaces.*;33import java.security.spec.AlgorithmParameterSpec;34import sun.nio.ch.DirectBuffer;3536import sun.security.util.*;37import sun.security.x509.AlgorithmId;3839import sun.security.rsa.RSASignature;40import sun.security.rsa.RSAPadding;4142import sun.security.pkcs11.wrapper.*;43import static sun.security.pkcs11.wrapper.PKCS11Constants.*;44import static sun.security.pkcs11.wrapper.PKCS11Exception.*;45import sun.security.util.KeyUtil;4647/**48* Signature implementation class. This class currently supports the49* following algorithms:50*51* . DSA52* . NONEwithDSA (RawDSA)53* . SHA1withDSA54* . SHA224withDSA55* . SHA256withDSA56* . SHA384withDSA57* . SHA512withDSA58* . SHA3-224withDSA59* . SHA3-256withDSA60* . SHA3-384withDSA61* . SHA3-512withDSA62* . <any of above>inP1363Format63* . RSA:64* . MD2withRSA65* . MD5withRSA66* . SHA1withRSA67* . SHA224withRSA68* . SHA256withRSA69* . SHA384withRSA70* . SHA512withRSA71* . SHA3-224withRSA72* . SHA3-256withRSA73* . SHA3-384withRSA74* . SHA3-512withRSA75* . ECDSA76* . NONEwithECDSA77* . SHA1withECDSA78* . SHA224withECDSA79* . SHA256withECDSA80* . SHA384withECDSA81* . SHA512withECDSA82* . SHA3_224withECDSA83* . SHA3_256withECDSA84* . SHA3_384withECDSA85* . SHA3_512withECDSA86* . <any of above>inP1363Format87*88* Note that the underlying PKCS#11 token may support complete signature89* algorithm (e.g. CKM_DSA_SHA1, CKM_MD5_RSA_PKCS), or it may just90* implement the signature algorithm without hashing (e.g. CKM_DSA, CKM_PKCS),91* or it may only implement the raw public key operation (CKM_RSA_X_509).92* This class uses what is available and adds whatever extra processing93* is needed.94*95* @author Andreas Sterbenz96* @since 1.597*/98final class P11Signature extends SignatureSpi {99100// token instance101private final Token token;102103// algorithm name104private final String algorithm;105106// name of the key algorithm, currently either RSA or DSA107private final String keyAlgorithm;108109// mechanism id110private final long mechanism;111112// digest algorithm OID, if we encode RSA signature ourselves113private final ObjectIdentifier digestOID;114115// type, one of T_* below116private final int type;117118// key instance used, if init*() was called119private P11Key p11Key;120121// message digest, if we do the digesting ourselves122private final MessageDigest md;123124// associated session, if any125private Session session;126127// mode, one of M_* below128private int mode;129130// flag indicating whether an operation is initialized131private boolean initialized;132133// buffer, for update(byte) or DSA134private final byte[] buffer;135136// total number of bytes processed in current operation137private int bytesProcessed;138139// The format, to be used for DSA and ECDSA signatures.140// If true, the IEEE P1363 format will be used, the concatenation of141// r and s. If false (default), the signature will be formatted as a142// DER-encoded ASN.1 sequence of r and s.143private boolean p1363Format = false;144145// constant for signing mode146private static final int M_SIGN = 1;147// constant for verification mode148private static final int M_VERIFY = 2;149150// constant for type digesting, we do the hashing ourselves151private static final int T_DIGEST = 1;152// constant for type update, token does everything153private static final int T_UPDATE = 2;154// constant for type raw, used with RawDSA and NONEwithECDSA only155private static final int T_RAW = 3;156157// PKCS#11 spec for CKM_ECDSA states that the length should not be longer158// than 1024 bits", but this is a little arbitrary159private static final int RAW_ECDSA_MAX = 128;160161162P11Signature(Token token, String algorithm, long mechanism)163throws NoSuchAlgorithmException, PKCS11Exception {164super();165this.token = token;166this.algorithm = algorithm;167this.mechanism = mechanism;168byte[] buffer = null;169ObjectIdentifier digestOID = null;170MessageDigest md = null;171switch ((int)mechanism) {172case (int)CKM_MD2_RSA_PKCS:173case (int)CKM_MD5_RSA_PKCS:174case (int)CKM_SHA1_RSA_PKCS:175case (int)CKM_SHA224_RSA_PKCS:176case (int)CKM_SHA256_RSA_PKCS:177case (int)CKM_SHA384_RSA_PKCS:178case (int)CKM_SHA512_RSA_PKCS:179case (int)CKM_SHA3_224_RSA_PKCS:180case (int)CKM_SHA3_256_RSA_PKCS:181case (int)CKM_SHA3_384_RSA_PKCS:182case (int)CKM_SHA3_512_RSA_PKCS:183keyAlgorithm = "RSA";184type = T_UPDATE;185buffer = new byte[1];186break;187case (int)CKM_DSA_SHA1:188case (int)CKM_DSA_SHA224:189case (int)CKM_DSA_SHA256:190case (int)CKM_DSA_SHA384:191case (int)CKM_DSA_SHA512:192case (int)CKM_DSA_SHA3_224:193case (int)CKM_DSA_SHA3_256:194case (int)CKM_DSA_SHA3_384:195case (int)CKM_DSA_SHA3_512:196keyAlgorithm = "DSA";197type = T_UPDATE;198buffer = new byte[1];199break;200case (int)CKM_ECDSA_SHA1:201case (int)CKM_ECDSA_SHA224:202case (int)CKM_ECDSA_SHA256:203case (int)CKM_ECDSA_SHA384:204case (int)CKM_ECDSA_SHA512:205case (int)CKM_ECDSA_SHA3_224:206case (int)CKM_ECDSA_SHA3_256:207case (int)CKM_ECDSA_SHA3_384:208case (int)CKM_ECDSA_SHA3_512:209keyAlgorithm = "EC";210type = T_UPDATE;211buffer = new byte[1];212break;213case (int)CKM_DSA:214keyAlgorithm = "DSA";215if (algorithm.equals("DSA") ||216algorithm.equals("DSAinP1363Format")) {217type = T_DIGEST;218md = MessageDigest.getInstance("SHA-1");219} else if (algorithm.equals("RawDSA") ||220algorithm.equals("RawDSAinP1363Format")) {221type = T_RAW;222buffer = new byte[20];223} else {224throw new ProviderException(algorithm);225}226break;227case (int)CKM_ECDSA:228keyAlgorithm = "EC";229if (algorithm.equals("NONEwithECDSA") ||230algorithm.equals("NONEwithECDSAinP1363Format")) {231type = T_RAW;232buffer = new byte[RAW_ECDSA_MAX];233} else {234type = T_DIGEST;235md = MessageDigest.getInstance236(getDigestEnum(algorithm).stdName());237}238break;239case (int)CKM_RSA_PKCS:240case (int)CKM_RSA_X_509:241keyAlgorithm = "RSA";242type = T_DIGEST;243KnownOIDs digestAlg = getDigestEnum(algorithm);244md = MessageDigest.getInstance(digestAlg.stdName());245digestOID = ObjectIdentifier.of(digestAlg);246break;247default:248throw new ProviderException("Unknown mechanism: " + mechanism);249}250this.buffer = buffer;251this.digestOID = digestOID;252this.md = md;253if (algorithm.endsWith("inP1363Format")) {254this.p1363Format = true;255}256}257258// reset the states to the pre-initialized values259private void reset(boolean doCancel) {260261if (!initialized) {262return;263}264initialized = false;265266try {267if (session == null) {268return;269}270271if (doCancel && token.explicitCancel) {272cancelOperation();273}274} finally {275p11Key.releaseKeyID();276session = token.releaseSession(session);277}278}279280private void cancelOperation() {281token.ensureValid();282// cancel operation by finishing it; avoid killSession as some283// hardware vendors may require re-login284try {285if (mode == M_SIGN) {286if (type == T_UPDATE) {287token.p11.C_SignFinal(session.id(), 0);288} else {289byte[] digest;290if (type == T_DIGEST) {291digest = md.digest();292} else { // T_RAW293digest = buffer;294}295token.p11.C_Sign(session.id(), digest);296}297} else { // M_VERIFY298byte[] signature;299if (mechanism == CKM_DSA) {300signature = new byte[64]; // assume N = 256301} else {302signature = new byte[(p11Key.length() + 7) >> 3];303}304if (type == T_UPDATE) {305token.p11.C_VerifyFinal(session.id(), signature);306} else {307byte[] digest;308if (type == T_DIGEST) {309digest = md.digest();310} else { // T_RAW311digest = buffer;312}313token.p11.C_Verify(session.id(), digest, signature);314}315}316} catch (PKCS11Exception e) {317if (e.getErrorCode() == CKR_OPERATION_NOT_INITIALIZED) {318// Cancel Operation may be invoked after an error on a PKCS#11319// call. If the operation inside the token was already cancelled,320// do not fail here. This is part of a defensive mechanism for321// PKCS#11 libraries that do not strictly follow the standard.322return;323}324if (mode == M_VERIFY) {325long errorCode = e.getErrorCode();326if ((errorCode == CKR_SIGNATURE_INVALID) ||327(errorCode == CKR_SIGNATURE_LEN_RANGE)) {328// expected since signature is incorrect329return;330}331}332throw new ProviderException("cancel failed", e);333}334}335336private void ensureInitialized() {337338if (!initialized) {339initialize();340}341}342343// assumes current state is initialized == false344private void initialize() {345346if (p11Key == null) {347throw new ProviderException(348"Operation cannot be performed without " +349"calling engineInit first");350}351long keyID = p11Key.getKeyID();352try {353token.ensureValid();354if (session == null) {355session = token.getOpSession();356}357if (mode == M_SIGN) {358token.p11.C_SignInit(session.id(),359new CK_MECHANISM(mechanism), keyID);360} else {361token.p11.C_VerifyInit(session.id(),362new CK_MECHANISM(mechanism), keyID);363}364} catch (PKCS11Exception e) {365p11Key.releaseKeyID();366session = token.releaseSession(session);367throw new ProviderException("Initialization failed", e);368}369if (bytesProcessed != 0) {370bytesProcessed = 0;371if (md != null) {372md.reset();373}374}375initialized = true;376}377378private void checkKeySize(String keyAlgo, Key key)379throws InvalidKeyException {380CK_MECHANISM_INFO mechInfo = null;381try {382mechInfo = token.getMechanismInfo(mechanism);383} catch (PKCS11Exception e) {384// should not happen, ignore for now.385}386if (mechInfo == null) {387// skip the check if no native info available388return;389}390int minKeySize = mechInfo.iMinKeySize;391int maxKeySize = mechInfo.iMaxKeySize;392393// need to override the MAX keysize for SHA1withDSA394if (md != null && mechanism == CKM_DSA && maxKeySize > 1024) {395maxKeySize = 1024;396}397int keySize = 0;398if (key instanceof P11Key) {399keySize = ((P11Key) key).length();400} else {401try {402if (keyAlgo.equals("RSA")) {403keySize = ((RSAKey) key).getModulus().bitLength();404} else if (keyAlgo.equals("DSA")) {405keySize = ((DSAKey) key).getParams().getP().bitLength();406} else if (keyAlgo.equals("EC")) {407keySize = ((ECKey) key).getParams().getCurve().getField().getFieldSize();408} else {409throw new ProviderException("Error: unsupported algo " + keyAlgo);410}411} catch (ClassCastException cce) {412throw new InvalidKeyException(keyAlgo +413" key must be the right type", cce);414}415}416if (keySize < minKeySize) {417throw new InvalidKeyException(keyAlgo +418" key must be at least " + minKeySize + " bits");419}420if (keySize > maxKeySize) {421throw new InvalidKeyException(keyAlgo +422" key must be at most " + maxKeySize + " bits");423}424if (keyAlgo.equals("RSA")) {425checkRSAKeyLength(keySize);426}427}428429private void checkRSAKeyLength(int len) throws InvalidKeyException {430RSAPadding padding;431try {432padding = RSAPadding.getInstance433(RSAPadding.PAD_BLOCKTYPE_1, (len + 7) >> 3);434} catch (InvalidAlgorithmParameterException iape) {435throw new InvalidKeyException(iape.getMessage());436}437int maxDataSize = padding.getMaxDataSize();438int encodedLength = switch (algorithm) {439case "MD5withRSA", "MD2withRSA" -> 34;440case "SHA1withRSA" -> 35;441case "SHA224withRSA", "SHA3-224withRSA" -> 47;442case "SHA256withRSA", "SHA3-256withRSA" -> 51;443case "SHA384withRSA", "SHA3-384withRSA" -> 67;444case "SHA512withRSA", "SHA3-512withRSA" -> 83;445default ->446throw new ProviderException("Unknown signature algo: " +447algorithm);448};449if (encodedLength > maxDataSize) {450throw new InvalidKeyException451("Key is too short for this signature algorithm");452}453}454455// see JCA spec456@Override457protected void engineInitVerify(PublicKey publicKey)458throws InvalidKeyException {459460if (publicKey == null) {461throw new InvalidKeyException("Key must not be null");462}463// Need to check key length whenever a new key is set464if (publicKey != p11Key) {465checkKeySize(keyAlgorithm, publicKey);466}467reset(true);468mode = M_VERIFY;469p11Key = P11KeyFactory.convertKey(token, publicKey, keyAlgorithm);470initialize();471}472473// see JCA spec474@Override475protected void engineInitSign(PrivateKey privateKey)476throws InvalidKeyException {477478if (privateKey == null) {479throw new InvalidKeyException("Key must not be null");480}481// Need to check RSA key length whenever a new key is set482if (privateKey != p11Key) {483checkKeySize(keyAlgorithm, privateKey);484}485reset(true);486mode = M_SIGN;487p11Key = P11KeyFactory.convertKey(token, privateKey, keyAlgorithm);488initialize();489}490491// see JCA spec492@Override493protected void engineUpdate(byte b) throws SignatureException {494ensureInitialized();495switch (type) {496case T_UPDATE:497buffer[0] = b;498engineUpdate(buffer, 0, 1);499break;500case T_DIGEST:501md.update(b);502bytesProcessed++;503break;504case T_RAW:505if (bytesProcessed >= buffer.length) {506bytesProcessed = buffer.length + 1;507return;508}509buffer[bytesProcessed++] = b;510break;511default:512throw new ProviderException("Internal error");513}514}515516// see JCA spec517@Override518protected void engineUpdate(byte[] b, int ofs, int len)519throws SignatureException {520521ensureInitialized();522if (len == 0) {523return;524}525// check for overflow526if (len + bytesProcessed < 0) {527throw new ProviderException("Processed bytes limits exceeded.");528}529switch (type) {530case T_UPDATE:531try {532if (mode == M_SIGN) {533token.p11.C_SignUpdate(session.id(), 0, b, ofs, len);534} else {535token.p11.C_VerifyUpdate(session.id(), 0, b, ofs, len);536}537bytesProcessed += len;538} catch (PKCS11Exception e) {539reset(false);540throw new ProviderException(e);541}542break;543case T_DIGEST:544md.update(b, ofs, len);545bytesProcessed += len;546break;547case T_RAW:548if (bytesProcessed + len > buffer.length) {549bytesProcessed = buffer.length + 1;550return;551}552System.arraycopy(b, ofs, buffer, bytesProcessed, len);553bytesProcessed += len;554break;555default:556throw new ProviderException("Internal error");557}558}559560// see JCA spec561@Override562protected void engineUpdate(ByteBuffer byteBuffer) {563564ensureInitialized();565int len = byteBuffer.remaining();566if (len <= 0) {567return;568}569switch (type) {570case T_UPDATE:571if (byteBuffer instanceof DirectBuffer == false) {572// cannot do better than default impl573super.engineUpdate(byteBuffer);574return;575}576long addr = ((DirectBuffer)byteBuffer).address();577int ofs = byteBuffer.position();578try {579if (mode == M_SIGN) {580token.p11.C_SignUpdate581(session.id(), addr + ofs, null, 0, len);582} else {583token.p11.C_VerifyUpdate584(session.id(), addr + ofs, null, 0, len);585}586bytesProcessed += len;587byteBuffer.position(ofs + len);588} catch (PKCS11Exception e) {589reset(false);590throw new ProviderException("Update failed", e);591}592break;593case T_DIGEST:594md.update(byteBuffer);595bytesProcessed += len;596break;597case T_RAW:598if (bytesProcessed + len > buffer.length) {599bytesProcessed = buffer.length + 1;600return;601}602byteBuffer.get(buffer, bytesProcessed, len);603bytesProcessed += len;604break;605default:606reset(false);607throw new ProviderException("Internal error");608}609}610611// see JCA spec612@Override613protected byte[] engineSign() throws SignatureException {614615ensureInitialized();616boolean doCancel = true;617try {618byte[] signature;619if (type == T_UPDATE) {620signature = token.p11.C_SignFinal(session.id(), 0);621} else {622byte[] digest;623if (type == T_DIGEST) {624digest = md.digest();625} else { // T_RAW626if (mechanism == CKM_DSA) {627if (bytesProcessed != buffer.length) {628throw new SignatureException629("Data for RawDSA must be exactly 20 bytes long");630}631digest = buffer;632} else { // CKM_ECDSA633if (bytesProcessed > buffer.length) {634throw new SignatureException("Data for NONEwithECDSA"635+ " must be at most " + RAW_ECDSA_MAX + " bytes long");636}637digest = new byte[bytesProcessed];638System.arraycopy(buffer, 0, digest, 0, bytesProcessed);639}640}641if (keyAlgorithm.equals("RSA") == false) {642// DSA and ECDSA643signature = token.p11.C_Sign(session.id(), digest);644} else { // RSA645byte[] data = encodeSignature(digest);646if (mechanism == CKM_RSA_X_509) {647data = pkcs1Pad(data);648}649signature = token.p11.C_Sign(session.id(), data);650}651}652doCancel = false;653654if (keyAlgorithm.equals("RSA")) {655return signature;656} else {657if (p1363Format) {658return signature;659} else {660return dsaToASN1(signature);661}662}663} catch (PKCS11Exception pe) {664// As per the PKCS#11 standard, C_Sign and C_SignFinal may only665// keep the operation active on CKR_BUFFER_TOO_SMALL errors or666// successful calls to determine the output length. However,667// these cases are handled at OpenJDK's libj2pkcs11 native668// library. Thus, doCancel can safely be 'false' here.669doCancel = false;670throw new ProviderException(pe);671} catch (SignatureException | ProviderException e) {672throw e;673} finally {674reset(doCancel);675}676}677678// see JCA spec679@Override680protected boolean engineVerify(byte[] signature) throws SignatureException {681682ensureInitialized();683boolean doCancel = true;684try {685if (!p1363Format) {686if (keyAlgorithm.equals("DSA")) {687signature = asn1ToDSA(signature);688} else if (keyAlgorithm.equals("EC")) {689signature = asn1ToECDSA(signature);690}691}692if (type == T_UPDATE) {693token.p11.C_VerifyFinal(session.id(), signature);694} else {695byte[] digest;696if (type == T_DIGEST) {697digest = md.digest();698} else { // T_RAW699if (mechanism == CKM_DSA) {700if (bytesProcessed != buffer.length) {701throw new SignatureException702("Data for RawDSA must be exactly 20 bytes long");703}704digest = buffer;705} else {706if (bytesProcessed > buffer.length) {707throw new SignatureException("Data for NONEwithECDSA"708+ " must be at most " + RAW_ECDSA_MAX + " bytes long");709}710digest = new byte[bytesProcessed];711System.arraycopy(buffer, 0, digest, 0, bytesProcessed);712}713}714if (keyAlgorithm.equals("RSA") == false) {715// DSA and ECDSA716token.p11.C_Verify(session.id(), digest, signature);717} else { // RSA718byte[] data = encodeSignature(digest);719if (mechanism == CKM_RSA_X_509) {720data = pkcs1Pad(data);721}722token.p11.C_Verify(session.id(), data, signature);723}724}725doCancel = false;726return true;727} catch (PKCS11Exception pe) {728doCancel = false;729long errorCode = pe.getErrorCode();730if (errorCode == CKR_SIGNATURE_INVALID) {731return false;732}733if (errorCode == CKR_SIGNATURE_LEN_RANGE) {734// return false rather than throwing an exception735return false;736}737// ECF bug?738if (errorCode == CKR_DATA_LEN_RANGE) {739return false;740}741throw new ProviderException(pe);742} catch (SignatureException | ProviderException e) {743throw e;744} finally {745reset(doCancel);746}747}748749private byte[] pkcs1Pad(byte[] data) {750try {751int len = (p11Key.length() + 7) >> 3;752RSAPadding padding = RSAPadding.getInstance753(RSAPadding.PAD_BLOCKTYPE_1, len);754byte[] padded = padding.pad(data);755return padded;756} catch (GeneralSecurityException e) {757throw new ProviderException(e);758}759}760761private byte[] encodeSignature(byte[] digest) throws SignatureException {762try {763return RSASignature.encodeSignature(digestOID, digest);764} catch (IOException e) {765throw new SignatureException("Invalid encoding", e);766}767}768769private static KnownOIDs getDigestEnum(String algorithm)770throws NoSuchAlgorithmException {771try {772String digAlg = SignatureUtil.extractDigestAlgFromDwithE(algorithm);773KnownOIDs k = KnownOIDs.findMatch(digAlg);774if (k == null) {775throw new NoSuchAlgorithmException776("Unsupported digest algorithm: " + digAlg);777}778return k;779} catch (IllegalArgumentException iae) {780// should never happen781throw new NoSuchAlgorithmException("Unknown signature: " +782algorithm, iae);783}784}785786// private static byte[] decodeSignature(byte[] signature) throws IOException {787// return RSASignature.decodeSignature(digestOID, signature);788// }789790// For DSA and ECDSA signatures, PKCS#11 represents them as a simple791// byte array that contains the concatenation of r and s.792// For DSA, r and s are always exactly 20 bytes long.793// For ECDSA, r and s are of variable length, but we know that each794// occupies half of the array.795private static byte[] dsaToASN1(byte[] signature) {796int n = signature.length >> 1;797BigInteger r = new BigInteger(1, P11Util.subarray(signature, 0, n));798BigInteger s = new BigInteger(1, P11Util.subarray(signature, n, n));799try {800DerOutputStream outseq = new DerOutputStream(100);801outseq.putInteger(r);802outseq.putInteger(s);803DerValue result = new DerValue(DerValue.tag_Sequence,804outseq.toByteArray());805return result.toByteArray();806} catch (java.io.IOException e) {807throw new RuntimeException("Internal error", e);808}809}810811private static byte[] asn1ToDSA(byte[] sig) throws SignatureException {812try {813// Enforce strict DER checking for signatures814DerInputStream in = new DerInputStream(sig, 0, sig.length, false);815DerValue[] values = in.getSequence(2);816817// check number of components in the read sequence818// and trailing data819if ((values.length != 2) || (in.available() != 0)) {820throw new IOException("Invalid encoding for signature");821}822823BigInteger r = values[0].getPositiveBigInteger();824BigInteger s = values[1].getPositiveBigInteger();825826byte[] br = toByteArray(r, 20);827byte[] bs = toByteArray(s, 20);828if ((br == null) || (bs == null)) {829throw new SignatureException("Out of range value for R or S");830}831return P11Util.concat(br, bs);832} catch (SignatureException e) {833throw e;834} catch (Exception e) {835throw new SignatureException("Invalid encoding for signature", e);836}837}838839private byte[] asn1ToECDSA(byte[] sig) throws SignatureException {840try {841// Enforce strict DER checking for signatures842DerInputStream in = new DerInputStream(sig, 0, sig.length, false);843DerValue[] values = in.getSequence(2);844845// check number of components in the read sequence846// and trailing data847if ((values.length != 2) || (in.available() != 0)) {848throw new IOException("Invalid encoding for signature");849}850851BigInteger r = values[0].getPositiveBigInteger();852BigInteger s = values[1].getPositiveBigInteger();853854// trim leading zeroes855byte[] br = KeyUtil.trimZeroes(r.toByteArray());856byte[] bs = KeyUtil.trimZeroes(s.toByteArray());857int k = Math.max(br.length, bs.length);858// r and s each occupy half the array859byte[] res = new byte[k << 1];860System.arraycopy(br, 0, res, k - br.length, br.length);861System.arraycopy(bs, 0, res, res.length - bs.length, bs.length);862return res;863} catch (Exception e) {864throw new SignatureException("Invalid encoding for signature", e);865}866}867868private static byte[] toByteArray(BigInteger bi, int len) {869byte[] b = bi.toByteArray();870int n = b.length;871if (n == len) {872return b;873}874if ((n == len + 1) && (b[0] == 0)) {875byte[] t = new byte[len];876System.arraycopy(b, 1, t, 0, len);877return t;878}879if (n > len) {880return null;881}882// must be smaller883byte[] t = new byte[len];884System.arraycopy(b, 0, t, (len - n), n);885return t;886}887888// see JCA spec889@SuppressWarnings("deprecation")890@Override891protected void engineSetParameter(String param, Object value)892throws InvalidParameterException {893throw new UnsupportedOperationException("setParameter() not supported");894}895896// see JCA spec897@Override898protected void engineSetParameter(AlgorithmParameterSpec params)899throws InvalidAlgorithmParameterException {900if (params != null) {901throw new InvalidAlgorithmParameterException("No parameter accepted");902}903}904905// see JCA spec906@SuppressWarnings("deprecation")907@Override908protected Object engineGetParameter(String param)909throws InvalidParameterException {910throw new UnsupportedOperationException("getParameter() not supported");911}912913// see JCA spec914@Override915protected AlgorithmParameters engineGetParameters() {916return null;917}918}919920921