Home | History | Annotate | Download | only in conscrypt
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package org.conscrypt;
     18 
     19 import java.security.AlgorithmParameters;
     20 import java.security.InvalidAlgorithmParameterException;
     21 import java.security.InvalidKeyException;
     22 import java.security.InvalidParameterException;
     23 import java.security.Key;
     24 import java.security.KeyFactory;
     25 import java.security.NoSuchAlgorithmException;
     26 import java.security.PrivateKey;
     27 import java.security.PublicKey;
     28 import java.security.SecureRandom;
     29 import java.security.SignatureException;
     30 import java.security.interfaces.RSAPrivateCrtKey;
     31 import java.security.interfaces.RSAPrivateKey;
     32 import java.security.interfaces.RSAPublicKey;
     33 import java.security.spec.AlgorithmParameterSpec;
     34 import java.security.spec.InvalidKeySpecException;
     35 import java.security.spec.InvalidParameterSpecException;
     36 import java.security.spec.MGF1ParameterSpec;
     37 import java.security.spec.PKCS8EncodedKeySpec;
     38 import java.security.spec.X509EncodedKeySpec;
     39 import java.util.Arrays;
     40 import java.util.Locale;
     41 import javax.crypto.BadPaddingException;
     42 import javax.crypto.Cipher;
     43 import javax.crypto.CipherSpi;
     44 import javax.crypto.IllegalBlockSizeException;
     45 import javax.crypto.NoSuchPaddingException;
     46 import javax.crypto.ShortBufferException;
     47 import javax.crypto.spec.OAEPParameterSpec;
     48 import javax.crypto.spec.PSource;
     49 import javax.crypto.spec.SecretKeySpec;
     50 
     51 /**
     52  * @hide
     53  */
     54 @Internal
     55 abstract class OpenSSLCipherRSA extends CipherSpi {
     56     /**
     57      * The current OpenSSL key we're operating on.
     58      */
     59     OpenSSLKey key;
     60 
     61     /**
     62      * Current key type: private or public.
     63      */
     64     boolean usingPrivateKey;
     65 
     66     /**
     67      * Current cipher mode: encrypting or decrypting.
     68      */
     69     boolean encrypting;
     70 
     71     /**
     72      * Buffer for operations
     73      */
     74     private byte[] buffer;
     75 
     76     /**
     77      * Current offset in the buffer.
     78      */
     79     private int bufferOffset;
     80 
     81     /**
     82      * Flag that indicates an exception should be thrown when the input is too
     83      * large during doFinal.
     84      */
     85     private boolean inputTooLarge;
     86 
     87     /**
     88      * Current padding mode
     89      */
     90     int padding = NativeConstants.RSA_PKCS1_PADDING;
     91 
     92     OpenSSLCipherRSA(int padding) {
     93         this.padding = padding;
     94     }
     95 
     96     @Override
     97     protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
     98         final String modeUpper = mode.toUpperCase(Locale.ROOT);
     99         if ("NONE".equals(modeUpper) || "ECB".equals(modeUpper)) {
    100             return;
    101         }
    102 
    103         throw new NoSuchAlgorithmException("mode not supported: " + mode);
    104     }
    105 
    106     @Override
    107     protected void engineSetPadding(String padding) throws NoSuchPaddingException {
    108         final String paddingUpper = padding.toUpperCase(Locale.ROOT);
    109         if ("PKCS1PADDING".equals(paddingUpper)) {
    110             this.padding = NativeConstants.RSA_PKCS1_PADDING;
    111             return;
    112         }
    113         if ("NOPADDING".equals(paddingUpper)) {
    114             this.padding = NativeConstants.RSA_NO_PADDING;
    115             return;
    116         }
    117 
    118         throw new NoSuchPaddingException("padding not supported: " + padding);
    119     }
    120 
    121     @Override
    122     protected int engineGetBlockSize() {
    123         if (encrypting) {
    124             return paddedBlockSizeBytes();
    125         }
    126         return keySizeBytes();
    127     }
    128 
    129     @Override
    130     protected int engineGetOutputSize(int inputLen) {
    131         if (encrypting) {
    132             return keySizeBytes();
    133         }
    134         return paddedBlockSizeBytes();
    135     }
    136 
    137     int paddedBlockSizeBytes() {
    138         int paddedBlockSizeBytes = keySizeBytes();
    139         if (padding == NativeConstants.RSA_PKCS1_PADDING) {
    140             paddedBlockSizeBytes--;  // for 0 prefix
    141             paddedBlockSizeBytes -= 10;  // PKCS1 padding header length
    142         }
    143         return paddedBlockSizeBytes;
    144     }
    145 
    146     int keySizeBytes() {
    147         if (!isInitialized()) {
    148             throw new IllegalStateException("cipher is not initialized");
    149         }
    150         return NativeCrypto.RSA_size(this.key.getNativeRef());
    151     }
    152 
    153     /**
    154      * Returns {@code true} if the cipher has been initialized.
    155      */
    156     boolean isInitialized() {
    157         return key != null;
    158     }
    159 
    160     @Override
    161     protected byte[] engineGetIV() {
    162         return null;
    163     }
    164 
    165     @Override
    166     protected AlgorithmParameters engineGetParameters() {
    167         return null;
    168     }
    169 
    170     void doCryptoInit(AlgorithmParameterSpec spec)
    171         throws InvalidAlgorithmParameterException, InvalidKeyException {}
    172 
    173     void engineInitInternal(int opmode, Key key, AlgorithmParameterSpec spec)
    174             throws InvalidKeyException, InvalidAlgorithmParameterException {
    175         if (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE) {
    176             encrypting = true;
    177         } else if (opmode == Cipher.DECRYPT_MODE || opmode == Cipher.UNWRAP_MODE) {
    178             encrypting = false;
    179         } else {
    180             throw new InvalidParameterException("Unsupported opmode " + opmode);
    181         }
    182 
    183         if (key instanceof OpenSSLRSAPrivateKey) {
    184             OpenSSLRSAPrivateKey rsaPrivateKey = (OpenSSLRSAPrivateKey) key;
    185             usingPrivateKey = true;
    186             this.key = rsaPrivateKey.getOpenSSLKey();
    187         } else if (key instanceof RSAPrivateCrtKey) {
    188             RSAPrivateCrtKey rsaPrivateKey = (RSAPrivateCrtKey) key;
    189             usingPrivateKey = true;
    190             this.key = OpenSSLRSAPrivateCrtKey.getInstance(rsaPrivateKey);
    191         } else if (key instanceof RSAPrivateKey) {
    192             RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) key;
    193             usingPrivateKey = true;
    194             this.key = OpenSSLRSAPrivateKey.getInstance(rsaPrivateKey);
    195         } else if (key instanceof OpenSSLRSAPublicKey) {
    196             OpenSSLRSAPublicKey rsaPublicKey = (OpenSSLRSAPublicKey) key;
    197             usingPrivateKey = false;
    198             this.key = rsaPublicKey.getOpenSSLKey();
    199         } else if (key instanceof RSAPublicKey) {
    200             RSAPublicKey rsaPublicKey = (RSAPublicKey) key;
    201             usingPrivateKey = false;
    202             this.key = OpenSSLRSAPublicKey.getInstance(rsaPublicKey);
    203         } else {
    204             if (null == key) {
    205                 throw new InvalidKeyException("RSA private or public key is null");
    206             }
    207 
    208             throw new InvalidKeyException("Need RSA private or public key");
    209         }
    210 
    211         buffer = new byte[NativeCrypto.RSA_size(this.key.getNativeRef())];
    212         bufferOffset = 0;
    213         inputTooLarge = false;
    214 
    215         doCryptoInit(spec);
    216     }
    217 
    218     @Override
    219     protected int engineGetKeySize(Key key) throws InvalidKeyException {
    220         if (key instanceof OpenSSLRSAPrivateKey) {
    221             return ((OpenSSLRSAPrivateKey) key).getModulus().bitLength();
    222         }
    223         if (key instanceof RSAPrivateCrtKey) {
    224             return ((RSAPrivateCrtKey) key).getModulus().bitLength();
    225         }
    226         if (key instanceof RSAPrivateKey) {
    227             return ((RSAPrivateKey) key).getModulus().bitLength();
    228         }
    229         if (key instanceof OpenSSLRSAPublicKey) {
    230             return ((OpenSSLRSAPublicKey) key).getModulus().bitLength();
    231         }
    232         if (key instanceof RSAPublicKey) {
    233             return ((RSAPublicKey) key).getModulus().bitLength();
    234         }
    235         if (null == key) {
    236             throw new InvalidKeyException("RSA private or public key is null");
    237         }
    238         throw new InvalidKeyException("Need RSA private or public key");
    239     }
    240 
    241     @Override
    242     protected void engineInit(int opmode, Key key, SecureRandom random) throws InvalidKeyException {
    243         try {
    244             engineInitInternal(opmode, key, null);
    245         } catch (InvalidAlgorithmParameterException e) {
    246             throw new InvalidKeyException("Algorithm parameters rejected when none supplied", e);
    247         }
    248     }
    249 
    250     @Override
    251     protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
    252             SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
    253         if (params != null) {
    254             throw new InvalidAlgorithmParameterException("unknown param type: "
    255                     + params.getClass().getName());
    256         }
    257 
    258         engineInitInternal(opmode, key, params);
    259     }
    260 
    261     @Override
    262     protected void engineInit(int opmode, Key key, AlgorithmParameters params, SecureRandom random)
    263             throws InvalidKeyException, InvalidAlgorithmParameterException {
    264         if (params != null) {
    265             throw new InvalidAlgorithmParameterException("unknown param type: "
    266                     + params.getClass().getName());
    267         }
    268 
    269         engineInitInternal(opmode, key, null);
    270     }
    271 
    272     @Override
    273     protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
    274         if (bufferOffset + inputLen > buffer.length) {
    275             inputTooLarge = true;
    276             return EmptyArray.BYTE;
    277         }
    278 
    279         System.arraycopy(input, inputOffset, buffer, bufferOffset, inputLen);
    280         bufferOffset += inputLen;
    281         return EmptyArray.BYTE;
    282     }
    283 
    284     @Override
    285     protected int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output,
    286             int outputOffset) throws ShortBufferException {
    287         engineUpdate(input, inputOffset, inputLen);
    288         return 0;
    289     }
    290 
    291     @Override
    292     protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
    293             throws IllegalBlockSizeException, BadPaddingException {
    294         if (input != null) {
    295             engineUpdate(input, inputOffset, inputLen);
    296         }
    297 
    298         if (inputTooLarge) {
    299             throw new IllegalBlockSizeException("input must be under " + buffer.length + " bytes");
    300         }
    301 
    302         final byte[] tmpBuf;
    303         if (bufferOffset != buffer.length) {
    304             if (padding == NativeConstants.RSA_NO_PADDING) {
    305                 tmpBuf = new byte[buffer.length];
    306                 System.arraycopy(buffer, 0, tmpBuf, buffer.length - bufferOffset, bufferOffset);
    307             } else {
    308                 tmpBuf = Arrays.copyOf(buffer, bufferOffset);
    309             }
    310         } else {
    311             tmpBuf = buffer;
    312         }
    313 
    314         byte[] output = new byte[buffer.length];
    315         int resultSize = doCryptoOperation(tmpBuf, output);
    316         if (!encrypting && resultSize != output.length) {
    317             output = Arrays.copyOf(output, resultSize);
    318         }
    319 
    320         bufferOffset = 0;
    321         return output;
    322     }
    323 
    324     abstract int doCryptoOperation(final byte[] tmpBuf, byte[] output)
    325             throws BadPaddingException, IllegalBlockSizeException;
    326 
    327     @Override
    328     protected int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output,
    329             int outputOffset) throws ShortBufferException, IllegalBlockSizeException,
    330             BadPaddingException {
    331         byte[] b = engineDoFinal(input, inputOffset, inputLen);
    332 
    333         final int lastOffset = outputOffset + b.length;
    334         if (lastOffset > output.length) {
    335             throw new ShortBufferException("output buffer is too small " + output.length + " < "
    336                     + lastOffset);
    337         }
    338 
    339         System.arraycopy(b, 0, output, outputOffset, b.length);
    340         return b.length;
    341     }
    342 
    343     @Override
    344     protected byte[] engineWrap(Key key) throws IllegalBlockSizeException, InvalidKeyException {
    345         try {
    346             byte[] encoded = key.getEncoded();
    347             return engineDoFinal(encoded, 0, encoded.length);
    348         } catch (BadPaddingException e) {
    349             IllegalBlockSizeException newE = new IllegalBlockSizeException();
    350             newE.initCause(e);
    351             throw newE;
    352         }
    353     }
    354 
    355     @Override
    356     protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
    357             int wrappedKeyType) throws InvalidKeyException, NoSuchAlgorithmException {
    358         try {
    359             byte[] encoded = engineDoFinal(wrappedKey, 0, wrappedKey.length);
    360             if (wrappedKeyType == Cipher.PUBLIC_KEY) {
    361                 KeyFactory keyFactory = KeyFactory.getInstance(wrappedKeyAlgorithm);
    362                 return keyFactory.generatePublic(new X509EncodedKeySpec(encoded));
    363             } else if (wrappedKeyType == Cipher.PRIVATE_KEY) {
    364                 KeyFactory keyFactory = KeyFactory.getInstance(wrappedKeyAlgorithm);
    365                 return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encoded));
    366             } else if (wrappedKeyType == Cipher.SECRET_KEY) {
    367                 return new SecretKeySpec(encoded, wrappedKeyAlgorithm);
    368             } else {
    369                 throw new UnsupportedOperationException("wrappedKeyType == " + wrappedKeyType);
    370             }
    371         } catch (IllegalBlockSizeException e) {
    372             throw new InvalidKeyException(e);
    373         } catch (BadPaddingException e) {
    374             throw new InvalidKeyException(e);
    375         } catch (InvalidKeySpecException e) {
    376             throw new InvalidKeyException(e);
    377         }
    378     }
    379 
    380     public abstract static class DirectRSA extends OpenSSLCipherRSA {
    381         public DirectRSA(int padding) {
    382             super(padding);
    383         }
    384 
    385         @Override
    386         int doCryptoOperation(final byte[] tmpBuf, byte[] output)
    387                 throws BadPaddingException, IllegalBlockSizeException {
    388             int resultSize;
    389             if (encrypting) {
    390                 if (usingPrivateKey) {
    391                     resultSize = NativeCrypto.RSA_private_encrypt(
    392                             tmpBuf.length, tmpBuf, output, key.getNativeRef(), padding);
    393                 } else {
    394                     resultSize = NativeCrypto.RSA_public_encrypt(
    395                             tmpBuf.length, tmpBuf, output, key.getNativeRef(), padding);
    396                 }
    397             } else {
    398                 try {
    399                     if (usingPrivateKey) {
    400                         resultSize = NativeCrypto.RSA_private_decrypt(
    401                                 tmpBuf.length, tmpBuf, output, key.getNativeRef(), padding);
    402                     } else {
    403                         resultSize = NativeCrypto.RSA_public_decrypt(
    404                                 tmpBuf.length, tmpBuf, output, key.getNativeRef(), padding);
    405                     }
    406                 } catch (SignatureException e) {
    407                     IllegalBlockSizeException newE = new IllegalBlockSizeException();
    408                     newE.initCause(e);
    409                     throw newE;
    410                 }
    411             }
    412             return resultSize;
    413         }
    414     }
    415 
    416     public static final class PKCS1 extends DirectRSA {
    417         public PKCS1() {
    418             super(NativeConstants.RSA_PKCS1_PADDING);
    419         }
    420     }
    421 
    422     public static final class Raw extends DirectRSA {
    423         public Raw() {
    424             super(NativeConstants.RSA_NO_PADDING);
    425         }
    426     }
    427 
    428     static class OAEP extends OpenSSLCipherRSA {
    429         private long oaepMd;
    430         private int oaepMdSizeBytes;
    431 
    432         private long mgf1Md;
    433 
    434         private byte[] label;
    435 
    436         private NativeRef.EVP_PKEY_CTX pkeyCtx;
    437 
    438         public OAEP(long defaultMd, int defaultMdSizeBytes) {
    439             super(NativeConstants.RSA_PKCS1_OAEP_PADDING);
    440             oaepMd = mgf1Md = defaultMd;
    441             oaepMdSizeBytes = defaultMdSizeBytes;
    442         }
    443 
    444         @Override
    445         protected AlgorithmParameters engineGetParameters() {
    446             if (!isInitialized()) {
    447                 return null;
    448             }
    449 
    450             try {
    451                 AlgorithmParameters params = AlgorithmParameters.getInstance("OAEP");
    452 
    453                 final PSource pSrc;
    454                 if (label == null) {
    455                     pSrc = PSource.PSpecified.DEFAULT;
    456                 } else {
    457                     pSrc = new PSource.PSpecified(label);
    458                 }
    459 
    460                 params.init(new OAEPParameterSpec(
    461                         EvpMdRef.getJcaDigestAlgorithmStandardNameFromEVP_MD(oaepMd),
    462                         EvpMdRef.MGF1_ALGORITHM_NAME,
    463                         new MGF1ParameterSpec(
    464                                 EvpMdRef.getJcaDigestAlgorithmStandardNameFromEVP_MD(mgf1Md)),
    465                         pSrc));
    466                 return params;
    467             } catch (NoSuchAlgorithmException e) {
    468                 // We should not get here.
    469                 throw (Error) new AssertionError("OAEP not supported").initCause(e);
    470             } catch (InvalidParameterSpecException e) {
    471                 throw new RuntimeException("No providers of AlgorithmParameters.OAEP available");
    472             }
    473         }
    474 
    475         @Override
    476         protected void engineSetPadding(String padding) throws NoSuchPaddingException {
    477             String paddingUpper = padding.toUpperCase(Locale.US);
    478             if (paddingUpper.equals("OAEPPADDING")) {
    479                 this.padding = NativeConstants.RSA_PKCS1_OAEP_PADDING;
    480                 return;
    481             }
    482 
    483             throw new NoSuchPaddingException("Only OAEP padding is supported");
    484         }
    485 
    486         @Override
    487         protected void engineInit(
    488                 int opmode, Key key, AlgorithmParameterSpec spec, SecureRandom random)
    489                 throws InvalidKeyException, InvalidAlgorithmParameterException {
    490             if (spec != null && !(spec instanceof OAEPParameterSpec)) {
    491                 throw new InvalidAlgorithmParameterException(
    492                         "Only OAEPParameterSpec accepted in OAEP mode");
    493             }
    494 
    495             engineInitInternal(opmode, key, spec);
    496         }
    497 
    498         @Override
    499         protected void engineInit(
    500                 int opmode, Key key, AlgorithmParameters params, SecureRandom random)
    501                 throws InvalidKeyException, InvalidAlgorithmParameterException {
    502             OAEPParameterSpec spec = null;
    503             if (params != null) {
    504                 try {
    505                     spec = params.getParameterSpec(OAEPParameterSpec.class);
    506                 } catch (InvalidParameterSpecException e) {
    507                     throw new InvalidAlgorithmParameterException(
    508                             "Only OAEP parameters are supported", e);
    509                 }
    510             }
    511 
    512             engineInitInternal(opmode, key, spec);
    513         }
    514 
    515         @Override
    516         void engineInitInternal(int opmode, Key key, AlgorithmParameterSpec spec)
    517                 throws InvalidKeyException, InvalidAlgorithmParameterException {
    518             if (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE) {
    519                 if (!(key instanceof PublicKey)) {
    520                     throw new InvalidKeyException("Only public keys may be used to encrypt");
    521                 }
    522             } else if (opmode == Cipher.DECRYPT_MODE || opmode == Cipher.UNWRAP_MODE) {
    523                 if (!(key instanceof PrivateKey)) {
    524                     throw new InvalidKeyException("Only private keys may be used to decrypt");
    525                 }
    526             }
    527             super.engineInitInternal(opmode, key, spec);
    528         }
    529 
    530         @Override
    531         void doCryptoInit(AlgorithmParameterSpec spec)
    532             throws InvalidAlgorithmParameterException, InvalidKeyException {
    533             pkeyCtx = new NativeRef.EVP_PKEY_CTX(encrypting
    534                             ? NativeCrypto.EVP_PKEY_encrypt_init(key.getNativeRef())
    535                             : NativeCrypto.EVP_PKEY_decrypt_init(key.getNativeRef()));
    536 
    537             if (spec instanceof OAEPParameterSpec) {
    538                 readOAEPParameters((OAEPParameterSpec) spec);
    539             }
    540 
    541             NativeCrypto.EVP_PKEY_CTX_set_rsa_padding(
    542                     pkeyCtx.context, NativeConstants.RSA_PKCS1_OAEP_PADDING);
    543             NativeCrypto.EVP_PKEY_CTX_set_rsa_oaep_md(pkeyCtx.context, oaepMd);
    544             NativeCrypto.EVP_PKEY_CTX_set_rsa_mgf1_md(pkeyCtx.context, mgf1Md);
    545             if (label != null && label.length > 0) {
    546                 NativeCrypto.EVP_PKEY_CTX_set_rsa_oaep_label(pkeyCtx.context, label);
    547             }
    548         }
    549 
    550         @Override
    551         int paddedBlockSizeBytes() {
    552             int paddedBlockSizeBytes = keySizeBytes();
    553             // Size described in step 2 of decoding algorithm, but extra byte
    554             // needed to make sure it's smaller than the RSA key modulus size.
    555             // https://tools.ietf.org/html/rfc2437#section-9.1.1.2
    556             return paddedBlockSizeBytes - (2 * oaepMdSizeBytes + 2);
    557         }
    558 
    559         private void readOAEPParameters(OAEPParameterSpec spec)
    560                 throws InvalidAlgorithmParameterException {
    561             String mgfAlgUpper = spec.getMGFAlgorithm().toUpperCase(Locale.US);
    562             AlgorithmParameterSpec mgfSpec = spec.getMGFParameters();
    563             if ((!EvpMdRef.MGF1_ALGORITHM_NAME.equals(mgfAlgUpper)
    564                         && !EvpMdRef.MGF1_OID.equals(mgfAlgUpper))
    565                     || !(mgfSpec instanceof MGF1ParameterSpec)) {
    566                 throw new InvalidAlgorithmParameterException(
    567                         "Only MGF1 supported as mask generation function");
    568             }
    569 
    570             MGF1ParameterSpec mgf1spec = (MGF1ParameterSpec) mgfSpec;
    571             String oaepAlgUpper = spec.getDigestAlgorithm().toUpperCase(Locale.US);
    572             try {
    573                 oaepMd = EvpMdRef.getEVP_MDByJcaDigestAlgorithmStandardName(oaepAlgUpper);
    574                 oaepMdSizeBytes =
    575                         EvpMdRef.getDigestSizeBytesByJcaDigestAlgorithmStandardName(oaepAlgUpper);
    576                 mgf1Md = EvpMdRef.getEVP_MDByJcaDigestAlgorithmStandardName(
    577                         mgf1spec.getDigestAlgorithm());
    578             } catch (NoSuchAlgorithmException e) {
    579                 throw new InvalidAlgorithmParameterException(e);
    580             }
    581 
    582             PSource pSource = spec.getPSource();
    583             if (!"PSpecified".equals(pSource.getAlgorithm())
    584                     || !(pSource instanceof PSource.PSpecified)) {
    585                 throw new InvalidAlgorithmParameterException(
    586                         "Only PSpecified accepted for PSource");
    587             }
    588             label = ((PSource.PSpecified) pSource).getValue();
    589         }
    590 
    591         @Override
    592         int doCryptoOperation(byte[] tmpBuf, byte[] output)
    593                 throws BadPaddingException, IllegalBlockSizeException {
    594             if (encrypting) {
    595                 return NativeCrypto.EVP_PKEY_encrypt(pkeyCtx, output, 0, tmpBuf, 0, tmpBuf.length);
    596             } else {
    597                 return NativeCrypto.EVP_PKEY_decrypt(pkeyCtx, output, 0, tmpBuf, 0, tmpBuf.length);
    598             }
    599         }
    600 
    601         public static final class SHA1 extends OAEP {
    602             public SHA1() {
    603                 super(EvpMdRef.SHA1.EVP_MD, EvpMdRef.SHA1.SIZE_BYTES);
    604             }
    605         }
    606 
    607         public static final class SHA224 extends OAEP {
    608             public SHA224() {
    609                 super(EvpMdRef.SHA224.EVP_MD, EvpMdRef.SHA224.SIZE_BYTES);
    610             }
    611         }
    612 
    613         public static final class SHA256 extends OAEP {
    614             public SHA256() {
    615                 super(EvpMdRef.SHA256.EVP_MD, EvpMdRef.SHA256.SIZE_BYTES);
    616             }
    617         }
    618 
    619         public static final class SHA384 extends OAEP {
    620             public SHA384() {
    621                 super(EvpMdRef.SHA384.EVP_MD, EvpMdRef.SHA384.SIZE_BYTES);
    622             }
    623         }
    624 
    625         public static final class SHA512 extends OAEP {
    626             public SHA512() {
    627                 super(EvpMdRef.SHA512.EVP_MD, EvpMdRef.SHA512.SIZE_BYTES);
    628             }
    629         }
    630     }
    631 }
    632