• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 com.android.rkpdapp.unittest;
18 
19 import static com.android.rkpdapp.unittest.Utils.generateEcdsaKeyPair;
20 import static com.android.rkpdapp.unittest.Utils.getP256PubKeyFromBytes;
21 import static com.android.rkpdapp.unittest.Utils.signPublicKey;
22 
23 import static com.google.common.truth.Truth.assertThat;
24 import static com.google.common.truth.Truth.assertWithMessage;
25 
26 import android.util.Base64;
27 
28 import androidx.test.ext.junit.runners.AndroidJUnit4;
29 
30 import com.android.rkpdapp.utils.X509Utils;
31 
32 import org.junit.Test;
33 import org.junit.runner.RunWith;
34 
35 import java.io.ByteArrayInputStream;
36 import java.io.ByteArrayOutputStream;
37 import java.io.InputStream;
38 import java.security.KeyPair;
39 import java.security.cert.CertificateException;
40 import java.security.cert.CertificateFactory;
41 import java.security.cert.X509Certificate;
42 
43 @RunWith(AndroidJUnit4.class)
44 public class X509UtilsTest {
45 
46     @Test
testFormatX509Certs()47     public void testFormatX509Certs() throws Exception {
48         KeyPair root = generateEcdsaKeyPair();
49         KeyPair intermediate = generateEcdsaKeyPair();
50         KeyPair leaf = generateEcdsaKeyPair();
51         X509Certificate[] certs = new X509Certificate[3];
52         certs[2] = signPublicKey(root, root.getPublic());
53         certs[1] = signPublicKey(root, intermediate.getPublic());
54         certs[0] = signPublicKey(intermediate, leaf.getPublic());
55         ByteArrayOutputStream os = new ByteArrayOutputStream();
56         for (X509Certificate cert : certs) {
57             os.write(cert.getEncoded());
58         }
59         X509Certificate[] roundTrip = X509Utils.formatX509Certs(os.toByteArray());
60         assertThat(certs.length).isEqualTo(roundTrip.length);
61         for (int i = 0; i < certs.length; i++) {
62             assertWithMessage("Failed on index " + i)
63                     .that(certs[i].getEncoded())
64                     .isEqualTo(roundTrip[i].getEncoded());
65         }
66     }
67 
68     @Test
testGetAndFormatRawPublicKey()69     public void testGetAndFormatRawPublicKey() throws Exception {
70         KeyPair testKey = generateEcdsaKeyPair();
71         X509Certificate testCert = signPublicKey(testKey, testKey.getPublic());
72         byte[] formattedKey = X509Utils.getAndFormatRawPublicKey(testCert);
73         byte[] xPoint = new byte[32];
74         byte[] yPoint = new byte[32];
75         System.arraycopy(formattedKey, 0 /* offset */, xPoint, 0 /* offset */, 32 /* length */);
76         System.arraycopy(formattedKey, 32 /* offset */, yPoint, 0 /* offset */, 32 /* length */);
77         assertThat(testKey.getPublic()).isEqualTo(getP256PubKeyFromBytes(xPoint, yPoint));
78     }
79 
80     @Test
testCertificateChains()81     public void testCertificateChains() throws Exception {
82         String encodedTestCert = "MIIBvTCCAWOgAwIBAgIRAKrDc87UaGSeFTRzF4vz0IcwCgYIKoZIzj0EAwIwIDEN"
83                 + "MAsGA1UECgwERmFrZTEPMA0GA1UEAwwGSXNzdWVyMCAXDTIzMDIwMTE1MzExMVoYDzIxMjMwMTA4MTU"
84                 + "zMTExWjA5MQwwCgYDVQQKDANURUUxKTAnBgNVBAMMIGFhYzM3M2NlZDQ2ODY0OWUxNTM0NzMxNzhiZj"
85                 + "NkMDg3MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEcC8SjTKkEqpPGQMXiZMC1/Dk3Fo/PsCZBI0E8"
86                 + "N4zXhBHJJZdT4LnYUNQXhSndDhrPO/x0MSySnz+hDZiRlRdzKNjMGEwHQYDVR0OBBYEFMcyyg91rTsG"
87                 + "QxM2hY2dfrmcYNIoMB8GA1UdIwQYMBaAFN2wvxbmHbqJicPAK1Ce+692JkfcMA8GA1UdEwEB/wQFMAM"
88                 + "BAf8wDgYDVR0PAQH/BAQDAgIEMAoGCCqGSM49BAMCA0gAMEUCIQD/ZJAabKvYlyuL6Ehc7bZMZFn9e7"
89                 + "Gu8f+QTA2fPjN/EQIgUeJPlHjNhoiu0QPpAoRbd4idOLyf5pqNEiXt7n8VDe0=";
90         String encodedRootCert = "MIIBpDCCAUmgAwIBAgIQf7TE7zQ0iDLyiZIIpqKCvjAKBggqhkjOPQQDAjAgMQ0w"
91                 + "CwYDVQQKDARGYWtlMQ8wDQYDVQQDDAZJc3N1ZXIwIBcNMjMwMjAxMTUxMDM0WhgPMjEyMzAxMDgxNTE"
92                 + "wMzRaMCAxDTALBgNVBAoMBEZha2UxDzANBgNVBAMMBklzc3VlcjBZMBMGByqGSM49AgEGCCqGSM49Aw"
93                 + "EHA0IABNh7P0mPpgFdSw9pC+aDMDRWnZa6g7H+jdy/a4V+erKJ+lDqdsV4Ao+2+vt2WelEP0DIZl51U"
94                 + "CaS8CKqZtRGLB6jYzBhMB0GA1UdDgQWBBTdsL8W5h26iYnDwCtQnvuvdiZH3DAfBgNVHSMEGDAWgBTd"
95                 + "sL8W5h26iYnDwCtQnvuvdiZH3DAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwICBDAKBggqhkj"
96                 + "OPQQDAgNJADBGAiEAm9Y2YGYe/2RqI6xMGq2IFJzeJ0qjfQzBLg6KjRLiJ10CIQCxpJCHRN4Gj17/ON"
97                 + "JGL2npbIsQVpSn1M5xPsY+9/qB1g==";
98 
99         X509Certificate rootCert = generateCertificateFromEncodedBytes(encodedRootCert);
100         X509Certificate testCert = generateCertificateFromEncodedBytes(encodedTestCert);
101         X509Certificate[] validCertChain = new X509Certificate[]{testCert, rootCert};
102         X509Certificate[] invalidCertChain = new X509Certificate[]{rootCert, testCert};
103 
104         assertThat(X509Utils.isCertChainValid(validCertChain)).isTrue();
105         assertThat(X509Utils.isCertChainValid(invalidCertChain)).isFalse();
106     }
107 
108     @Test
testCertChainSwapOAndCN()109     public void testCertChainSwapOAndCN() throws Exception {
110         String encodedTestCert = "MIIBvTCCAWOgAwIBAgIRAKrDc87UaGSeFTRzF4vz0IcwCgYIKoZIzj0EAwIwIDEP"
111                 + "MA0GA1UEAwwGSXNzdWVyMQ0wCwYDVQQKDARGYWtlMCAXDTIzMDIwMTE1MzExMVoYDzIxMjMwMTA4MTU"
112                 + "zMTExWjA5MQwwCgYDVQQKDANURUUxKTAnBgNVBAMMIGFhYzM3M2NlZDQ2ODY0OWUxNTM0NzMxNzhiZj"
113                 + "NkMDg3MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEcC8SjTKkEqpPGQMXiZMC1/Dk3Fo/PsCZBI0E8"
114                 + "N4zXhBHJJZdT4LnYUNQXhSndDhrPO/x0MSySnz+hDZiRlRdzKNjMGEwHQYDVR0OBBYEFMcyyg91rTsG"
115                 + "QxM2hY2dfrmcYNIoMB8GA1UdIwQYMBaAFN2wvxbmHbqJicPAK1Ce+692JkfcMA8GA1UdEwEB/wQFMAM"
116                 + "BAf8wDgYDVR0PAQH/BAQDAgIEMAoGCCqGSM49BAMCA0gAMEUCIQD/ZJAabKvYlyuL6Ehc7bZMZFn9e7"
117                 + "Gu8f+QTA2fPjN/EQIgUeJPlHjNhoiu0QPpAoRbd4idOLyf5pqNEiXt7n8VDe0=";
118         String encodedRootCert = "MIIBpDCCAUmgAwIBAgIQf7TE7zQ0iDLyiZIIpqKCvjAKBggqhkjOPQQDAjAgMQ0w"
119                 + "CwYDVQQKDARGYWtlMQ8wDQYDVQQDDAZJc3N1ZXIwIBcNMjMwMjAxMTUxMDM0WhgPMjEyMzAxMDgxNTE"
120                 + "wMzRaMCAxDTALBgNVBAoMBEZha2UxDzANBgNVBAMMBklzc3VlcjBZMBMGByqGSM49AgEGCCqGSM49Aw"
121                 + "EHA0IABNh7P0mPpgFdSw9pC+aDMDRWnZa6g7H+jdy/a4V+erKJ+lDqdsV4Ao+2+vt2WelEP0DIZl51U"
122                 + "CaS8CKqZtRGLB6jYzBhMB0GA1UdDgQWBBTdsL8W5h26iYnDwCtQnvuvdiZH3DAfBgNVHSMEGDAWgBTd"
123                 + "sL8W5h26iYnDwCtQnvuvdiZH3DAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwICBDAKBggqhkj"
124                 + "OPQQDAgNJADBGAiEAm9Y2YGYe/2RqI6xMGq2IFJzeJ0qjfQzBLg6KjRLiJ10CIQCxpJCHRN4Gj17/ON"
125                 + "JGL2npbIsQVpSn1M5xPsY+9/qB1g==";
126 
127         X509Certificate rootCert = generateCertificateFromEncodedBytes(encodedRootCert);
128         X509Certificate testCert = generateCertificateFromEncodedBytes(encodedTestCert);
129         X509Certificate[] certChain = new X509Certificate[]{testCert, rootCert};
130 
131         assertThat(X509Utils.isSelfSignedCertificate(rootCert)).isTrue();
132         assertThat(X509Utils.isSelfSignedCertificate(testCert)).isFalse();
133         assertThat(X509Utils.isCertChainValid(certChain)).isFalse();
134     }
135 
generateCertificateFromEncodedBytes(String encodedCert)136     private X509Certificate generateCertificateFromEncodedBytes(String encodedCert)
137             throws CertificateException {
138         CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
139         InputStream in = new ByteArrayInputStream(Base64.decode(encodedCert, Base64.DEFAULT));
140         return (X509Certificate) certFactory.generateCertificate(in);
141     }
142 }
143