]> git.saurik.com Git - apple/security.git/blob - SecuritySNACCRuntime/c++-lib/src/cdsaUtils.cpp
Security-54.tar.gz
[apple/security.git] / SecuritySNACCRuntime / c++-lib / src / cdsaUtils.cpp
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
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
64 * know.
65 */
66 static int SC_BDecPDU(
67 AsnType &asnObj,
68 BUF_TYPE b,
69 AsnLen &bytesDecoded)
70 {
71 ENV_TYPE env;
72
73 bytesDecoded = 0;
74 try {
75 asnObj.BDec(b, bytesDecoded, env);
76 return !b.ReadError();
77 }
78 catch(...) {
79 return false;
80 }
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 }
190
191 /*
192 * Explicitly non-inlined SnaccError throw
193 */
194 void SnaccExcep::throwMe(int err)
195 {
196 throw SnaccExcep(err);
197 }