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 "OIDs.h"
39 #include "TpmASN1_fp.h"
40 #include "X509_ECC_fp.h"
41 #include "X509_spt_fp.h"
42 #include "CryptHash_fp.h"
43
44 //** Functions
45
46 //*** X509PushPoint()
47 // This seems like it might be used more than once so...
48 // Return Type: INT16
49 // > 0 number of bytes added
50 // == 0 failure
51 INT16
X509PushPoint(ASN1MarshalContext * ctx,TPMS_ECC_POINT * p)52 X509PushPoint(
53 ASN1MarshalContext *ctx,
54 TPMS_ECC_POINT *p
55 )
56 {
57 // Push a bit string containing the public key. For now, push the x, and y
58 // coordinates of the public point, bottom up
59 ASN1StartMarshalContext(ctx); // BIT STRING
60 {
61 ASN1PushBytes(ctx, p->y.t.size, p->y.t.buffer);
62 ASN1PushBytes(ctx, p->x.t.size, p->x.t.buffer);
63 ASN1PushByte(ctx, 0x04);
64 }
65 return ASN1EndEncapsulation(ctx, ASN1_BITSTRING); // Ends BIT STRING
66 }
67
68 //*** X509AddSigningAlgorithmECC()
69 // This creates the singing algorithm data.
70 // Return Type: INT16
71 // > 0 number of bytes added
72 // == 0 failure
73 INT16
X509AddSigningAlgorithmECC(OBJECT * signKey,TPMT_SIG_SCHEME * scheme,ASN1MarshalContext * ctx)74 X509AddSigningAlgorithmECC(
75 OBJECT *signKey,
76 TPMT_SIG_SCHEME *scheme,
77 ASN1MarshalContext *ctx
78 )
79 {
80 PHASH_DEF hashDef = CryptGetHashDef(scheme->details.any.hashAlg);
81 //
82 NOT_REFERENCED(signKey);
83 // If the desired hashAlg definition wasn't found...
84 if(hashDef->hashAlg != scheme->details.any.hashAlg)
85 return 0;
86
87 switch(scheme->scheme)
88 {
89 #if ALG_ECDSA
90 case TPM_ALG_ECDSA:
91 // Make sure that we have an OID for this hash and ECC
92 if((hashDef->ECDSA)[0] != ASN1_OBJECT_IDENTIFIER)
93 break;
94 // if this is just an implementation check, indicate that this
95 // combination is supported
96 if(!ctx)
97 return 1;
98 ASN1StartMarshalContext(ctx);
99 ASN1PushOID(ctx, hashDef->ECDSA);
100 return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE);
101 #endif // ALG_ECDSA
102 default:
103 break;
104 }
105 return 0;
106 }
107
108
109 //*** X509AddPublicECC()
110 // This function will add the publicKey description to the DER data. If ctx is
111 // NULL, then no data is transferred and this function will indicate if the TPM
112 // has the values for DER-encoding of the public key.
113 // Return Type: INT16
114 // > 0 number of bytes added
115 // == 0 failure
116 INT16
X509AddPublicECC(OBJECT * object,ASN1MarshalContext * ctx)117 X509AddPublicECC(
118 OBJECT *object,
119 ASN1MarshalContext *ctx
120 )
121 {
122 const BYTE *curveOid =
123 CryptEccGetOID(object->publicArea.parameters.eccDetail.curveID);
124 if((curveOid == NULL) || (*curveOid != ASN1_OBJECT_IDENTIFIER))
125 return 0;
126 //
127 //
128 // SEQUENCE (2 elem) 1st
129 // SEQUENCE (2 elem) 2nd
130 // OBJECT IDENTIFIER 1.2.840.10045.2.1 ecPublicKey (ANSI X9.62 public key type)
131 // OBJECT IDENTIFIER 1.2.840.10045.3.1.7 prime256v1 (ANSI X9.62 named curve)
132 // BIT STRING (520 bit) 000001001010000111010101010111001001101101000100000010...
133 //
134 // If this is a check to see if the key can be encoded, it can.
135 // Need to mark the end sequence
136 if(ctx == NULL)
137 return 1;
138 ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 1st
139 {
140 X509PushPoint(ctx, &object->publicArea.unique.ecc); // BIT STRING
141 ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 2nd
142 {
143 ASN1PushOID(ctx, curveOid); // curve dependent
144 ASN1PushOID(ctx, OID_ECC_PUBLIC); // (1.2.840.10045.2.1)
145 }
146 ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // Ends SEQUENCE 2nd
147 }
148 return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // Ends SEQUENCE 1st
149 }
150