src/java.base/share/classes/sun/security/rsa/RSAPadding.java
branchJDK-8145252-TLS13-branch
changeset 56542 56aaa6cb3693
parent 47216 71c04702a3d5
equal deleted inserted replaced
56541:92cbbfc996f3 56542:56aaa6cb3693
     1 /*
     1 /*
     2  * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
     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.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    37 import sun.security.jca.JCAUtil;
    37 import sun.security.jca.JCAUtil;
    38 
    38 
    39 /**
    39 /**
    40  * RSA padding and unpadding.
    40  * RSA padding and unpadding.
    41  *
    41  *
    42  * The various PKCS#1 versions can be found in the EMC/RSA Labs
    42  * The various PKCS#1 versions can be found in the IETF RFCs
    43  * web site, which is currently:
    43  * tracking the corresponding PKCS#1 standards.
    44  *
    44  *
    45  *     http://www.emc.com/emc-plus/rsa-labs/index.htm
    45  *     RFC 2313: PKCS#1 v1.5
    46  *
    46  *     RFC 2437: PKCS#1 v2.0
    47  * or in the IETF RFCs derived from the above PKCS#1 standards.
    47  *     RFC 3447: PKCS#1 v2.1
    48  *
    48  *     RFC 8017: PKCS#1 v2.2
    49  *     RFC 2313: v1.5
       
    50  *     RFC 2437: v2.0
       
    51  *     RFC 3447: v2.1
       
    52  *
    49  *
    53  * The format of PKCS#1 v1.5 padding is:
    50  * The format of PKCS#1 v1.5 padding is:
    54  *
    51  *
    55  *   0x00 | BT | PS...PS | 0x00 | data...data
    52  *   0x00 | BT | PS...PS | 0x00 | data...data
    56  *
    53  *
   103     private SecureRandom random;
   100     private SecureRandom random;
   104 
   101 
   105     // maximum size of the data
   102     // maximum size of the data
   106     private final int maxDataSize;
   103     private final int maxDataSize;
   107 
   104 
   108     // OAEP: main messagedigest
   105     // OAEP: main message digest
   109     private MessageDigest md;
   106     private MessageDigest md;
   110 
   107 
   111     // OAEP: message digest for MGF1
   108     // OAEP: MGF1
   112     private MessageDigest mgfMd;
   109     private MGF1 mgf;
   113 
   110 
   114     // OAEP: value of digest of data (user-supplied or zero-length) using md
   111     // OAEP: value of digest of data (user-supplied or zero-length) using md
   115     private byte[] lHash;
   112     private byte[] lHash;
   116 
   113 
   117     /**
   114     /**
   162         case PAD_NONE:
   159         case PAD_NONE:
   163             maxDataSize = paddedSize;
   160             maxDataSize = paddedSize;
   164             break;
   161             break;
   165         case PAD_OAEP_MGF1:
   162         case PAD_OAEP_MGF1:
   166             String mdName = "SHA-1";
   163             String mdName = "SHA-1";
   167             String mgfMdName = "SHA-1";
   164             String mgfMdName = mdName;
   168             byte[] digestInput = null;
   165             byte[] digestInput = null;
   169             try {
   166             try {
   170                 if (spec != null) {
   167                 if (spec != null) {
   171                     mdName = spec.getDigestAlgorithm();
   168                     mdName = spec.getDigestAlgorithm();
   172                     String mgfName = spec.getMGFAlgorithm();
   169                     String mgfName = spec.getMGFAlgorithm();
   183                             ("Unsupported pSource algo: " + pSrcAlgo);
   180                             ("Unsupported pSource algo: " + pSrcAlgo);
   184                     }
   181                     }
   185                     digestInput = ((PSource.PSpecified) pSrc).getValue();
   182                     digestInput = ((PSource.PSpecified) pSrc).getValue();
   186                 }
   183                 }
   187                 md = MessageDigest.getInstance(mdName);
   184                 md = MessageDigest.getInstance(mdName);
   188                 mgfMd = MessageDigest.getInstance(mgfMdName);
   185                 mgf = new MGF1(mgfMdName);
   189             } catch (NoSuchAlgorithmException e) {
   186             } catch (NoSuchAlgorithmException e) {
   190                 throw new InvalidKeyException
   187                 throw new InvalidKeyException("Digest not available", e);
   191                         ("Digest " + mdName + " not available", e);
       
   192             }
   188             }
   193             lHash = getInitialHash(md, digestInput);
   189             lHash = getInitialHash(md, digestInput);
   194             int digestLen = lHash.length;
   190             int digestLen = lHash.length;
   195             maxDataSize = paddedSize - 2 - 2 * digestLen;
   191             maxDataSize = paddedSize - 2 - 2 * digestLen;
   196             if (maxDataSize <= 0) {
   192             if (maxDataSize <= 0) {
   197                 throw new InvalidKeyException
   193                 throw new InvalidKeyException
   198                         ("Key is too short for encryption using OAEPPadding" +
   194                         ("Key is too short for encryption using OAEPPadding" +
   199                          " with " + mdName + " and MGF1" + mgfMdName);
   195                          " with " + mdName + " and " + mgf.getName());
   200             }
   196             }
   201             break;
   197             break;
   202         default:
   198         default:
   203             throw new InvalidKeyException("Invalid padding: " + type);
   199             throw new InvalidKeyException("Invalid padding: " + type);
   204         }
   200         }
   429         System.arraycopy(lHash, 0, EM, dbStart, hLen);
   425         System.arraycopy(lHash, 0, EM, dbStart, hLen);
   430         EM[mStart - 1] = 1;
   426         EM[mStart - 1] = 1;
   431         System.arraycopy(M, 0, EM, mStart, M.length);
   427         System.arraycopy(M, 0, EM, mStart, M.length);
   432 
   428 
   433         // produce maskedDB
   429         // produce maskedDB
   434         mgf1(EM, seedStart, seedLen, EM, dbStart, dbLen);
   430         mgf.generateAndXor(EM, seedStart, seedLen, dbLen, EM, dbStart);
   435 
   431 
   436         // produce maskSeed
   432         // produce maskSeed
   437         mgf1(EM, dbStart, dbLen, EM, seedStart, seedLen);
   433         mgf.generateAndXor(EM, dbStart, dbLen, seedLen, EM, seedStart);
   438 
   434 
   439         return EM;
   435         return EM;
   440     }
   436     }
   441 
   437 
   442     /**
   438     /**
   455         int seedLen = hLen;
   451         int seedLen = hLen;
   456 
   452 
   457         int dbStart = hLen + 1;
   453         int dbStart = hLen + 1;
   458         int dbLen = EM.length - dbStart;
   454         int dbLen = EM.length - dbStart;
   459 
   455 
   460         mgf1(EM, dbStart, dbLen, EM, seedStart, seedLen);
   456         mgf.generateAndXor(EM, dbStart, dbLen, seedLen, EM, seedStart);
   461         mgf1(EM, seedStart, seedLen, EM, dbStart, dbLen);
   457         mgf.generateAndXor(EM, seedStart, seedLen, dbLen, EM, dbStart);
   462 
   458 
   463         // verify lHash == lHash'
   459         // verify lHash == lHash'
   464         for (int i = 0; i < hLen; i++) {
   460         for (int i = 0; i < hLen; i++) {
   465             if (lHash[i] != EM[dbStart + i]) {
   461             if (lHash[i] != EM[dbStart + i]) {
   466                 bp = true;
   462                 bp = true;
   504             throw bpe;
   500             throw bpe;
   505         } else {
   501         } else {
   506             return m;
   502             return m;
   507         }
   503         }
   508     }
   504     }
   509 
       
   510     /**
       
   511      * Compute MGF1 using mgfMD as the message digest.
       
   512      * Note that we combine MGF1 with the XOR operation to reduce data
       
   513      * copying.
       
   514      *
       
   515      * We generate maskLen bytes of MGF1 from the seed and XOR it into
       
   516      * out[] starting at outOfs;
       
   517      */
       
   518     private void mgf1(byte[] seed, int seedOfs, int seedLen,
       
   519             byte[] out, int outOfs, int maskLen)  throws BadPaddingException {
       
   520         byte[] C = new byte[4]; // 32 bit counter
       
   521         byte[] digest = new byte[mgfMd.getDigestLength()];
       
   522         while (maskLen > 0) {
       
   523             mgfMd.update(seed, seedOfs, seedLen);
       
   524             mgfMd.update(C);
       
   525             try {
       
   526                 mgfMd.digest(digest, 0, digest.length);
       
   527             } catch (DigestException e) {
       
   528                 // should never happen
       
   529                 throw new BadPaddingException(e.toString());
       
   530             }
       
   531             for (int i = 0; (i < digest.length) && (maskLen > 0); maskLen--) {
       
   532                 out[outOfs++] ^= digest[i++];
       
   533             }
       
   534             if (maskLen > 0) {
       
   535                 // increment counter
       
   536                 for (int i = C.length - 1; (++C[i] == 0) && (i > 0); i--) {
       
   537                     // empty
       
   538                 }
       
   539             }
       
   540         }
       
   541     }
       
   542 }
   505 }