1 /* Microsoft Reference Implementation for TPM 2.0
2 *
3 * The copyright in this software is being made available under the BSD License,
4 * included below. This software may be subject to other third party and
5 * contributor rights, including patent rights, and no such rights are granted
6 * under this license.
7 *
8 * Copyright (c) Microsoft Corporation
9 *
10 * All rights reserved.
11 *
12 * BSD License
13 *
14 * Redistribution and use in source and binary forms, with or without modification,
15 * are permitted provided that the following conditions are met:
16 *
17 * Redistributions of source code must retain the above copyright notice, this list
18 * of conditions and the following disclaimer.
19 *
20 * Redistributions in binary form must reproduce the above copyright notice, this
21 * list of conditions and the following disclaimer in the documentation and/or
22 * other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35 //** Includes
36 #include "Tpm.h"
37 #include "X509.h"
38 #include "TpmASN1_fp.h"
39 #include "X509_RSA_fp.h"
40 #include "X509_spt_fp.h"
41 #include "CryptHash_fp.h"
42 #include "CryptRsa_fp.h"
43
44 //** Functions
45
46 #if ALG_RSA
47
48 //*** X509AddSigningAlgorithmRSA()
49 // This creates the singing algorithm data.
50 // Return Type: INT16
51 // > 0 number of bytes added
52 // == 0 failure
53 INT16
X509AddSigningAlgorithmRSA(OBJECT * signKey,TPMT_SIG_SCHEME * scheme,ASN1MarshalContext * ctx)54 X509AddSigningAlgorithmRSA(
55 OBJECT *signKey,
56 TPMT_SIG_SCHEME *scheme,
57 ASN1MarshalContext *ctx
58 )
59 {
60 TPM_ALG_ID hashAlg = scheme->details.any.hashAlg;
61 PHASH_DEF hashDef = CryptGetHashDef(hashAlg);
62 //
63 NOT_REFERENCED(signKey);
64 // return failure if hash isn't implemented
65 if(hashDef->hashAlg != hashAlg)
66 return 0;
67 switch(scheme->scheme)
68 {
69 case TPM_ALG_RSASSA:
70 {
71 // if the hash is implemented but there is no PKCS1 OID defined
72 // then this is not a valid signing combination.
73 if(hashDef->PKCS1[0] != ASN1_OBJECT_IDENTIFIER)
74 break;
75 if(ctx == NULL)
76 return 1;
77 return X509PushAlgorithmIdentifierSequence(ctx, hashDef->PKCS1);
78 }
79 case TPM_ALG_RSAPSS:
80 // leave if this is just an implementation check
81 if(ctx == NULL)
82 return 1;
83 // In the case of SHA1, everything is default and RFC4055 says that
84 // implementations that do signature generation MUST omit the parameter
85 // when defaults are used. )-:
86 if(hashDef->hashAlg == TPM_ALG_SHA1)
87 {
88 return X509PushAlgorithmIdentifierSequence(ctx, OID_RSAPSS);
89 }
90 else
91 {
92 // Going to build something that looks like:
93 // SEQUENCE (2 elem)
94 // OBJECT IDENTIFIER 1.2.840.113549.1.1.10 rsaPSS (PKCS #1)
95 // SEQUENCE (3 elem)
96 // [0] (1 elem)
97 // SEQUENCE (2 elem)
98 // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256
99 // NULL
100 // [1] (1 elem)
101 // SEQUENCE (2 elem)
102 // OBJECT IDENTIFIER 1.2.840.113549.1.1.8 pkcs1-MGF
103 // SEQUENCE (2 elem)
104 // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256
105 // NULL
106 // [2] (1 elem) salt length
107 // INTEGER 32
108
109 // The indentation is just to keep track of where we are in the
110 // structure
111 ASN1StartMarshalContext(ctx); // SEQUENCE (2 elements)
112 {
113 ASN1StartMarshalContext(ctx); // SEQUENCE (3 elements)
114 {
115 // [2] (1 elem) salt length
116 // INTEGER 32
117 ASN1StartMarshalContext(ctx);
118 {
119 INT16 saltSize =
120 CryptRsaPssSaltSize((INT16)hashDef->digestSize,
121 (INT16)signKey->publicArea.unique.rsa.t.size);
122 ASN1PushUINT(ctx, saltSize);
123 }
124 ASN1EndEncapsulation(ctx, ASN1_APPLICAIION_SPECIFIC + 2);
125
126 // Add the mask generation algorithm
127 // [1] (1 elem)
128 // SEQUENCE (2 elem) 1st
129 // OBJECT IDENTIFIER 1.2.840.113549.1.1.8 pkcs1-MGF
130 // SEQUENCE (2 elem) 2nd
131 // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256
132 // NULL
133 ASN1StartMarshalContext(ctx); // mask context [1] (1 elem)
134 {
135 ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 1st
136 // Handle the 2nd Sequence (sequence (object, null))
137 {
138 // This adds a NULL, then an OID and a SEQUENCE
139 // wrapper.
140 X509PushAlgorithmIdentifierSequence(ctx,
141 hashDef->OID);
142 // add the pkcs1-MGF OID
143 ASN1PushOID(ctx, OID_MGF1);
144 }
145 // End outer sequence
146 ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);
147 }
148 // End the [1]
149 ASN1EndEncapsulation(ctx, ASN1_APPLICAIION_SPECIFIC + 1);
150
151 // Add the hash algorithm
152 // [0] (1 elem)
153 // SEQUENCE (2 elem) (done by
154 // X509PushAlgorithmIdentifierSequence)
155 // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256 (NIST)
156 // NULL
157 ASN1StartMarshalContext(ctx); // [0] (1 elem)
158 {
159 X509PushAlgorithmIdentifierSequence(ctx, hashDef->OID);
160 }
161 ASN1EndEncapsulation(ctx, (ASN1_APPLICAIION_SPECIFIC + 0));
162 }
163 // SEQUENCE (3 elements) end
164 ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);
165
166 // RSA PSS OID
167 // OBJECT IDENTIFIER 1.2.840.113549.1.1.10 rsaPSS (PKCS #1)
168 ASN1PushOID(ctx, OID_RSAPSS);
169 }
170 // End Sequence (2 elements)
171 return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);
172 }
173 default:
174 break;
175 }
176 return 0;
177 }
178
179 //*** X509AddPublicRSA()
180 // This function will add the publicKey description to the DER data. If fillPtr is
181 // NULL, then no data is transferred and this function will indicate if the TPM
182 // has the values for DER-encoding of the public key.
183 // Return Type: INT16
184 // > 0 number of bytes added
185 // == 0 failure
186 INT16
X509AddPublicRSA(OBJECT * object,ASN1MarshalContext * ctx)187 X509AddPublicRSA(
188 OBJECT *object,
189 ASN1MarshalContext *ctx
190 )
191 {
192 UINT32 exp = object->publicArea.parameters.rsaDetail.exponent;
193 //
194 /*
195 SEQUENCE (2 elem) 1st
196 SEQUENCE (2 elem) 2nd
197 OBJECT IDENTIFIER 1.2.840.113549.1.1.1 rsaEncryption (PKCS #1)
198 NULL
199 BIT STRING (1 elem)
200 SEQUENCE (2 elem) 3rd
201 INTEGER (2048 bit) 2197304513741227955725834199357401�
202 INTEGER 65537
203 */
204 // If this is a check to see if the key can be encoded, it can.
205 // Need to mark the end sequence
206 if(ctx == NULL)
207 return 1;
208 ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 1st
209 ASN1StartMarshalContext(ctx); // BIT STRING
210 ASN1StartMarshalContext(ctx); // SEQUENCE *(2 elem) 3rd
211
212 // Get public exponent in big-endian byte order.
213 if(exp == 0)
214 exp = RSA_DEFAULT_PUBLIC_EXPONENT;
215
216 // Push a 4 byte integer. This might get reduced if there are leading zeros or
217 // extended if the high order byte is negative.
218 ASN1PushUINT(ctx, exp);
219 // Push the public key as an integer
220 ASN1PushInteger(ctx, object->publicArea.unique.rsa.t.size,
221 object->publicArea.unique.rsa.t.buffer);
222 // Embed this in a SEQUENCE tag and length in for the key, exponent sequence
223 ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // SEQUENCE (3rd)
224
225 // Embed this in a BIT STRING
226 ASN1EndEncapsulation(ctx, ASN1_BITSTRING);
227
228 // Now add the formatted SEQUENCE for the RSA public key OID. This is a
229 // fully constructed value so it doesn't need to have a context started
230 X509PushAlgorithmIdentifierSequence(ctx, OID_PKCS1_PUB);
231
232 return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);
233 }
234
235 #endif // ALG_RSA
236