]>
Commit | Line | Data |
---|---|---|
bac41a7b A |
1 | /* |
2 | * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. | |
3 | * | |
4 | * The contents of this file constitute Original Code as defined in and are | |
5 | * subject to the Apple Public Source License Version 1.2 (the 'License'). | |
6 | * You may not use this file except in compliance with the License. Please obtain | |
7 | * a copy of the License at http://www.apple.com/publicsource and read it before | |
8 | * using this file. | |
9 | * | |
10 | * This Original Code and all software distributed under the License are | |
11 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS | |
12 | * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT | |
13 | * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | |
14 | * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the | |
15 | * specific language governing rights and limitations under the License. | |
16 | */ | |
17 | ||
18 | ||
19 | /* | |
20 | * cdsaUtils.cpp - utility functions for CDSA-related code | |
21 | */ | |
22 | ||
23 | #include "cdsaUtils.h" | |
24 | #include <Security/cssmerr.h> | |
25 | ||
26 | #ifdef NDEBUG | |
27 | ||
28 | #include <Security/globalizer.h> | |
29 | ||
30 | /* silent cerr substitute */ | |
31 | ModuleNexus<Asn1ErrorClass> AsnNullError; | |
32 | #endif /* NDEBUG */ | |
33 | ||
34 | /* malloc/copy AsnBits.bits -->CssmOwnedData */ | |
35 | void SC_asnBitsToCssmData( | |
36 | const AsnBits &bits, | |
37 | CssmOwnedData &oData) | |
38 | { | |
39 | size_t len = (bits.BitLen() + 7) / 8; | |
40 | oData.copy(reinterpret_cast<const uint8 *>(bits.BitOcts()), len); | |
41 | } | |
42 | ||
43 | /* given DER-encoded bit string, decoded it and malloc/copy results | |
44 | * back to a CssmOwnedData */ | |
45 | void SC_decodeAsnBitsToCssmData( | |
46 | const CssmData encodedBits, | |
47 | CssmOwnedData &oData) | |
48 | { | |
49 | AsnBits decodedBits; | |
50 | SC_decodeAsnObj(encodedBits, decodedBits); | |
51 | size_t len = (decodedBits.BitLen() + 7) / 8; | |
52 | oData.copy(reinterpret_cast<const uint8 *>(decodedBits.BitOcts()), len); | |
53 | } | |
54 | ||
55 | /* | |
56 | * Universal BDecPdu/BEncPdu replacements, used below in SC_decodeAsnObj and | |
57 | * SC_encodeAsnObj. | |
58 | * | |
59 | * All AsnType subclasses implement this either via PDU_MEMBER_MACROS | |
60 | * for SecuritySNACCRuntime built-in types, or explicitly for all | |
61 | * other classes using asn-useful.h. To faciliate a global "one | |
29654253 A |
62 | * routine for encode/decode" which operates on AsnType &'s, we have |
63 | * to explicitly provide this here. Why this is not in AsnType, I don't | |
bac41a7b A |
64 | * know. |
65 | */ | |
66 | static int SC_BDecPDU( | |
67 | AsnType &asnObj, | |
68 | BUF_TYPE b, | |
69 | AsnLen &bytesDecoded) | |
70 | { | |
71 | ENV_TYPE env; | |
bac41a7b A |
72 | |
73 | bytesDecoded = 0; | |
29654253 | 74 | try { |
bac41a7b A |
75 | asnObj.BDec(b, bytesDecoded, env); |
76 | return !b.ReadError(); | |
77 | } | |
29654253 | 78 | catch(...) { |
bac41a7b | 79 | return false; |
29654253 | 80 | } |
bac41a7b A |
81 | } |
82 | ||
83 | static int SC_BEncPdu( | |
84 | AsnType &asnObj, | |
85 | BUF_TYPE b, | |
86 | AsnLen &bytesEncoded) | |
87 | { | |
88 | bytesEncoded = asnObj.BEnc(b); | |
89 | return !b.WriteError(); | |
90 | } | |
91 | ||
92 | /* DER-decode any AsnType object */ | |
93 | void SC_decodeAsnObj( | |
94 | const CssmData &derEncoded, | |
95 | AsnType &asnObj) | |
96 | { | |
97 | AsnBuf buf; | |
98 | size_t len = (size_t)derEncoded.length(); | |
99 | ||
100 | buf.InstallData(reinterpret_cast<char *>(derEncoded.data()), len); | |
101 | if(!SC_BDecPDU(asnObj, buf, len)) { | |
102 | CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); | |
103 | } | |
104 | } | |
105 | ||
106 | /* | |
107 | * DER-encode any AsnType object. | |
108 | * Unfortunately the call has to give an estimate of the max encoded size of | |
109 | * the result. There is no way (that I know of) to figure this out at encode | |
110 | * time. If this turns out to be a problem we might have to do a retry, | |
111 | * doubling the size of the encoded buffer. Be liberal; the maxEncodedSize | |
112 | * buffer is only temporary - due to snacc encoding style, a copy out is | |
113 | * necessary in any case, so the mallocd size of encodedBuf is exactly the | |
114 | * right size. | |
115 | */ | |
116 | void SC_encodeAsnObj( | |
117 | AsnType &asnObj, | |
118 | CssmOwnedData &derEncoded, | |
119 | size_t maxEncodedSize) | |
120 | { | |
121 | CssmAutoData aData(derEncoded.allocator); // temp encode target | |
122 | aData.malloc(maxEncodedSize); | |
123 | memset(aData.data(), 0, maxEncodedSize); | |
124 | AsnBuf encBuf; | |
125 | encBuf.Init(static_cast<char *>(aData.data()), maxEncodedSize); | |
126 | encBuf.ResetInWriteRvsMode(); | |
127 | AsnLen encoded; | |
128 | int rtn = SC_BEncPdu(asnObj, encBuf, encoded); | |
129 | if(encoded > maxEncodedSize) { | |
130 | CssmError::throwMe(CSSMERR_CSSM_BUFFER_TOO_SMALL); | |
131 | } | |
132 | if(!rtn) { | |
133 | /* not sure how this can happen... */ | |
134 | CssmError::throwMe(CSSMERR_CSSM_BUFFER_TOO_SMALL); | |
135 | } | |
136 | /* success; copy out to caller */ | |
137 | derEncoded.get().clear(); | |
138 | derEncoded.copy(encBuf.DataPtr(), encBuf.DataLen()); | |
139 | } | |
140 | ||
141 | /* | |
142 | * Given a contentLength, obtain the length of the DER length encoding. | |
143 | */ | |
144 | size_t SC_lengthOfLength( | |
145 | size_t contentLen) | |
146 | { | |
147 | if(contentLen < 128) { | |
148 | return 1; | |
149 | } | |
150 | else if(contentLen < 256) { | |
151 | return 2; | |
152 | } | |
153 | else if(contentLen < 65536) { | |
154 | return 3; | |
155 | } | |
156 | else if(contentLen < 16777126) { | |
157 | return 4; | |
158 | } | |
159 | else { | |
160 | return 5; | |
161 | } | |
162 | } | |
163 | ||
164 | /* | |
165 | * Encode a DER length field. Pass in the lengthOfLength if you've obtained | |
166 | * it in a previous call to SC_lengthOfLength. | |
167 | */ | |
168 | void SC_encodeLength( | |
169 | size_t contentLen, | |
170 | void *cp, | |
171 | size_t lengthOfLength) | |
172 | { | |
173 | if(lengthOfLength == 0) { | |
174 | lengthOfLength = SC_lengthOfLength(contentLen); | |
175 | } | |
176 | unsigned char *ucp = reinterpret_cast<unsigned char *>(cp); | |
177 | if(lengthOfLength == 1) { | |
178 | /* easy case */ | |
179 | *ucp = contentLen; | |
180 | return; | |
181 | } | |
182 | lengthOfLength--; | |
183 | *ucp = (0x80 + lengthOfLength); | |
184 | ucp += lengthOfLength; | |
185 | for(size_t i=0; i<lengthOfLength; i++) { | |
186 | *ucp-- = contentLen & 0xff; | |
187 | contentLen >>= 8; | |
188 | } | |
189 | } | |
29654253 A |
190 | |
191 | /* | |
192 | * Explicitly non-inlined SnaccError throw | |
193 | */ | |
194 | void SnaccExcep::throwMe(int err) | |
195 | { | |
196 | throw SnaccExcep(err); | |
197 | } |