]> WPIA git - gigi.git/blob - src/club/wpia/gigi/crypto/key/KeyCheckROCA.java
Merge "add: show more certificates on the "roots" page"
[gigi.git] / src / club / wpia / gigi / crypto / key / KeyCheckROCA.java
1 /*
2  * Copyright (c) 2017, CRoCS, EnigmaBridge Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all
12  * copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22 /*
23  * Credits: ported to Java by Martin Paljak
24  */
25 /*
26  * Credits: ported to Gigi KeyCheck interface by Benny Baumann
27  */
28
29 package club.wpia.gigi.crypto.key;
30
31 import java.math.BigInteger;
32 import java.security.PublicKey;
33 import java.security.interfaces.RSAPublicKey;
34
35 import club.wpia.gigi.GigiApiException;
36
37 /**
38  * Due to a bug in several chips produced by Infineon several cryptographic
39  * processors in smartcards and other HSM appliances produced RSA keys with a
40  * weakness that made them subject for easy factorization. The vulnerability has
41  * been present in Infineon's library from about 2014 through 2017 making keys
42  * up to 2048 bit RSA practically factorable and strongly weakens larger RSA
43  * keys produced with such an implementation. This check implements a
44  * fingerprinting mechanism detecting such keys using a heuristic found by the
45  * researchers describing the vulnerability. Any such keys SHALL NOT be
46  * certified. This implementation is based on the Java port by Martin Paljak.
47  *
48  * @see <a href="https://crocs.fi.muni.cz/public/papers/rsa_ccs17">Original ROCA
49  *      vulnerability website</a>
50  * @see <a href="https://arstechnica.com/?post_type=post&p=1186901">Report by
51  *      ArsTechnica on ROCA</a>
52  * @see <a
53  *      href="https://gist.github.com/hannob/ad37d9e9e3cbf3b89bc0a8fc80cb9475">Gist
54  *      by Hanno Böck detailling impacted keys</a>
55  * @see <a
56  *      href="https://github.com/crocs-muni/roca/blob/master/java/BrokenKey.java">Java
57  *      port by Martin Paljak</a>
58  */
59 public class KeyCheckROCA extends KeyCheck {
60
61     /**
62      * List of Lengths of masks for the listed {@link #markers}.
63      */
64     private static final int[] prims = new int[] {
65             11, 13, 17, 19, 37, 53, 61, 71, 73, 79, 97, 103, 107, 109, 127, 151, 157
66     };
67
68     private static final BigInteger[] primes = new BigInteger[prims.length];
69
70     /**
71      * List of markers used to fingerprint keys vulnerable to ROCA.
72      *
73      * This list is reduced according to:
74      * {@link https://groups.google.com/d/msg/mozilla.dev.security.policy/4RqKdD0FeF4/DcxMqchSAQAJ}
75      */
76     private static final BigInteger[] markers = new BigInteger[] {
77             new BigInteger("1026"), // 11:402
78             new BigInteger("5658"), // 13:161a
79             new BigInteger("107286"), // 17:1a316
80             new BigInteger("199410"), // 19:30af2
81             new BigInteger("67109890"), // 37:4000402
82             new BigInteger("5310023542746834"), // 53:12dd703303aed2
83             new BigInteger("1455791217086302986"), // 61:1434026619900b0a
84             new BigInteger("20052041432995567486"), // 71:1164729716b1d977e
85             new BigInteger("6041388139249378920330"), // 73:147811a48004962078a
86             new BigInteger("207530445072488465666"), // 79:b4010404000640502
87             new BigInteger("79228162521181866724264247298"), // 97:1000000006000001800000002
88             new BigInteger("1760368345969468176824550810518"), // 103:16380e9115bd964257768fe396
89             new BigInteger("50079290986288516948354744811034"), // 107:27816ea9821633397be6a897e1a
90             new BigInteger("473022961816146413042658758988474"), // 109:1752639f4e85b003685cbe7192ba
91             new BigInteger("144390480366845522447407333004847678774"), // 127:6ca09850c2813205a04c81430a190536
92             new BigInteger("1800793591454480341970779146165214289059119882"), // 151:50c018bc00482458dac35b1a2412003d18030a
93             new BigInteger("126304807362733370595828809000324029340048915994"), // 157:161fb414d76af63826461899071bd5baca0b7e1a
94     };
95
96     static {
97         for (int i = 0; i < prims.length; i++) {
98             primes[i] = BigInteger.valueOf(prims[i]);
99         }
100
101         register(new KeyCheckROCA());
102     }
103
104     @Override
105     public void check(PublicKey key) throws GigiApiException {
106
107         if ( !(key instanceof RSAPublicKey)) {
108             return;
109         }
110
111         BigInteger modulus = ((RSAPublicKey) key).getModulus();
112
113         for (int i = 0; i < primes.length; i++) {
114             if (BigInteger.ONE.shiftLeft(modulus.remainder(primes[i]).intValue()).and(markers[i]).equals(BigInteger.ZERO)) {
115                 return;
116             }
117         }
118
119         throw new GigiApiException("ROCA vulnerability check for public key: Key likely vulnerable as fingerprint matches.");
120
121     }
122
123 }