Imported Upstream version 1.1.0
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / adapter_util / pkix / cert.c
1 /******************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      LICENSE-2.0" target="_blank">http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19
20  ******************************************************************/
21
22
23 #include "byte_array.h"
24 #include "cert.h"
25 #include "der_dec.h"
26
27
28 extern const uint8_t g_ECDSA_WITH_SHA256_OID[];
29 extern const uint8_t g_EC_PUBLIC_KEY_OID[];
30 extern const uint8_t g_PRIME_256_V1_OID[];
31
32 /**
33  * Decodes TBSCertificate.
34  */
35 static PKIError DecodeTbs(CertificateX509 *const crt)
36 {
37     FUNCTION_INIT(
38         size_t length, temp_len;
39         ByteArray tbs = crt->tbs, temp;
40         CHECK_NULL(crt, PKI_NULL_PASSED);
41     );
42     //skip version
43     SKIP_DER_FIELD(tbs, DER_VERSION, length);
44     //serial number
45     COPY_DER_FIELD(tbs, crt, serNum, DER_INTEGER, length);
46
47     CHECK_EQUAL(*(tbs.data), DER_SEQUENCE, PKI_INVALID_FORMAT);
48     CHECK_CALL(DecodeLength , &tbs, &length);
49     //copy to temp
50     temp = tbs; // OPTIONAL
51     INC_BYTE_ARRAY(tbs, length); // skip algorithm identifier
52     //check_signature_algorithm
53     //1.2.840.10045.4.3.2
54     CHECK_DER_OID(temp, g_ECDSA_WITH_SHA256_OID, ECDSA_WITH_SHA256_OID_LEN, temp_len);
55     //copy issuer X.500 name
56     COPY_DER_FIELD(tbs, crt, issuer, DER_SEQUENCE, length);
57     CHECK_EQUAL(*(tbs.data), DER_SEQUENCE, PKI_INVALID_FORMAT);
58     CHECK_CALL(DecodeLength , &tbs, &length);
59
60     //copy valid period
61     COPY_DER_FIELD(tbs, crt, validFrom, DER_UTC_TIME, length);
62     COPY_DER_FIELD(tbs, crt, validTo, DER_UTC_TIME, length);
63
64     //copy subject X.500 name
65     COPY_DER_FIELD(tbs, crt, subject, DER_SEQUENCE, length);
66     //public key
67     CHECK_EQUAL(*(tbs.data), DER_SEQUENCE, PKI_INVALID_FORMAT);
68     CHECK_CALL(DecodeLength , &tbs, &length);
69     CHECK_EQUAL(*(tbs.data), DER_SEQUENCE, PKI_INVALID_FORMAT);
70     CHECK_CALL(DecodeLength , &tbs, &length);
71     //check public key type
72     //1.2.840.10045.2.1
73     CHECK_DER_OID(tbs, g_EC_PUBLIC_KEY_OID, EC_PUBLIC_KEY_OID_LEN, length);
74     INC_BYTE_ARRAY(tbs, length);
75     //check curve
76     //1.2.840.10045.3.1.7
77     CHECK_DER_OID(tbs, g_PRIME_256_V1_OID, PRIME_256_V1_OID_LEN, length);
78     INC_BYTE_ARRAY(tbs, length);
79     //copy public key
80     COPY_DER_FIELD(tbs, crt, pubKey, DER_BIT_STRING, length);
81     FUNCTION_CLEAR();
82 }
83
84
85 /**
86  * Decodes certificate in DER format.
87  */
88 PKIError DecodeCertificate(ByteArray code, CertificateX509 *crt)
89 {
90     FUNCTION_INIT(
91         size_t length, tempLen;
92         ByteArray temp;
93         CHECK_NULL(crt, PKI_NULL_PASSED);
94         CHECK_NULL(code.data, PKI_NULL_PASSED);
95     );
96     CHECK_EQUAL(*(code.data), DER_SEQUENCE, PKI_INVALID_FORMAT);
97     CHECK_CALL(DecodeLength , &code, &length);
98     //store sequence position
99     temp = code;
100     //TODO check length of TBS
101     //copy tbs
102     COPY_DER_FIELD(code, crt, tbs, DER_SEQUENCE, length);
103     //decode tbs
104     CHECK_CALL(DecodeTbs, crt);
105     //include sequense and len to tbs
106     crt->tbs.len +=  crt->tbs.data - temp.data;
107     crt->tbs.data = temp.data;
108     //printf("DATA %02X\n", *(code.data));
109     CHECK_EQUAL(*(code.data), DER_SEQUENCE, PKI_INVALID_FORMAT);
110     CHECK_CALL(DecodeLength , &code, &length);
111     //copy to temp
112     temp = code;
113     INC_BYTE_ARRAY(code, length); // skip algorithm identifier
114     //check_signature_algorithm
115     //1.2.840.10045.4.3.2
116     CHECK_DER_OID(temp, g_ECDSA_WITH_SHA256_OID, ECDSA_WITH_SHA256_OID_LEN, tempLen);
117     //decode_signature_value
118     CHECK_EQUAL(*(code.data), DER_BIT_STRING, PKI_INVALID_FORMAT);
119     CHECK_CALL(DecodeLength , &code, &length);
120     //skip DER_UNIVERSAL
121     CHECK_EQUAL(*(code.data), DER_UNIVERSAL, PKI_INVALID_FORMAT);
122     CHECK_INC_BYTE_ARRAY(code, 1);
123     CHECK_EQUAL(*(code.data), DER_SEQUENCE, PKI_INVALID_FORMAT);
124     CHECK_CALL(DecodeLength , &code, &length);
125     //copy sign r value
126     COPY_DER_FIELD(code, crt, signR, DER_INTEGER, length);
127     //copy sign s value
128     COPY_DER_FIELD(code, crt, signS, DER_INTEGER, length);
129
130     PARSE_SIGNATURE(crt);
131
132     FUNCTION_CLEAR();
133 }
134
135 #ifdef X509_DEBUG
136 /**
137  * Prints certificate to console.
138  */
139 PKIError PrintCertificate(const CertificateX509 *const crt)
140 {
141     FUNCTION_INIT(
142         CHECK_NULL(crt, PKI_NULL_PASSED);
143     );
144     printf("\n-----BEGIN CERTIFICATE-----\n");
145     PRINT_BYTE_ARRAY("SER NUM:\n", crt->serNum);
146     PRINT_BYTE_ARRAY("ISSUER:\n", crt->issuer);
147     PRINT_BYTE_ARRAY("SUBJECT:\n", crt->subject);
148     PRINT_BYTE_ARRAY("PUB KEY:\n", crt->pubKey);
149     PRINT_BYTE_ARRAY("SIGN R VALUE:\n", crt->signR);
150     PRINT_BYTE_ARRAY("SIGN S VALUE:\n", crt->signS);
151     PRINT_BYTE_ARRAY("TBS:\n", crt->tbs);
152     printf("-----END CERTIFICATE-----\n");
153     FUNCTION_CLEAR(
154     );
155 }
156 #endif
157
158 PKIError ParsePublicKey(ByteArray *caPublicKey)
159 {
160     FUNCTION_INIT(
161         CHECK_NULL(caPublicKey, PKI_NULL_PASSED);
162     );
163
164     if ((caPublicKey->len == PUBLIC_KEY_SIZE + 2) && (caPublicKey->data[0] == 0)
165         && (caPublicKey->data[1] == ASN1_UNCOMPRESSED_KEY))
166         INC_BYTE_ARRAY(*caPublicKey, 2);
167     else if (caPublicKey->len != PUBLIC_KEY_SIZE)
168         CHECK_NULL(NULL, PKI_WRONG_ARRAY_LEN);
169
170     FUNCTION_CLEAR();
171 }