xref: /aosp_15_r20/external/ms-tpm-20-ref/TPMCmd/tpm/src/X509/X509_RSA.c (revision 5c591343844d1f9da7da26467c4bf7efc8a7a413)
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