]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
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 | * RSA_asymmetric.cpp - CSPContext for RSA asymmetric encryption | |
21 | */ | |
22 | ||
23 | #include "RSA_asymmetric.h" | |
24 | #include "RSA_DSA_utils.h" | |
25 | #include <security_utilities/debugging.h> | |
26 | #include <opensslUtils/opensslUtils.h> | |
27 | ||
fa7225c8 A |
28 | #define rsaCryptDebug(args...) secinfo("rsaCrypt", ## args) |
29 | #define rbprintf(args...) secinfo("rsaBuf", ## args) | |
b1ab9ed8 A |
30 | |
31 | static ModuleNexus<Mutex> gMutex; | |
32 | ||
33 | RSA_CryptContext::~RSA_CryptContext() | |
34 | { | |
35 | StLock<Mutex> _(gMutex()); | |
36 | if(mAllocdRsaKey) { | |
37 | assert(mRsaKey != NULL); | |
38 | RSA_free(mRsaKey); | |
39 | mRsaKey = NULL; | |
40 | mAllocdRsaKey = false; | |
41 | } | |
42 | } | |
43 | ||
44 | /* called by CSPFullPluginSession */ | |
45 | void RSA_CryptContext::init(const Context &context, bool encoding /*= true*/) | |
46 | { | |
47 | StLock<Mutex> _(gMutex()); | |
48 | ||
49 | if(mInitFlag && !opStarted()) { | |
50 | /* reusing - e.g. query followed by encrypt */ | |
51 | return; | |
52 | } | |
53 | ||
54 | /* optional mode to use alternate key class (e.g., decrypt with public key) */ | |
55 | CSSM_KEYCLASS keyClass; | |
56 | switch (context.getInt(CSSM_ATTRIBUTE_MODE)) { | |
57 | case CSSM_ALGMODE_PUBLIC_KEY: | |
58 | keyClass = CSSM_KEYCLASS_PUBLIC_KEY; | |
59 | break; | |
60 | case CSSM_ALGMODE_PRIVATE_KEY: | |
61 | keyClass = CSSM_KEYCLASS_PRIVATE_KEY; | |
62 | break; | |
63 | case CSSM_ALGMODE_NONE: | |
64 | /* default, not present in context: infer from op type */ | |
65 | keyClass = encoding ? CSSM_KEYCLASS_PUBLIC_KEY : CSSM_KEYCLASS_PRIVATE_KEY; | |
66 | break; | |
67 | default: | |
68 | CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_MODE); | |
69 | } | |
70 | ||
71 | /* fetch key from context */ | |
72 | if(mRsaKey == NULL) { | |
73 | assert(!opStarted()); | |
74 | CSSM_DATA label = {0, NULL}; | |
75 | mRsaKey = contextToRsaKey(context, | |
76 | session(), | |
77 | keyClass, | |
78 | encoding ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT, | |
79 | mAllocdRsaKey, | |
80 | label); | |
81 | if(label.Data) { | |
82 | mLabel.copy(label); | |
83 | mOaep = true; | |
84 | free(label.Data); | |
85 | } | |
86 | } | |
87 | else { | |
d64be36e | 88 | assert(opStarted()); |
b1ab9ed8 A |
89 | } |
90 | ||
91 | unsigned cipherBlockSize = RSA_size(mRsaKey); | |
92 | unsigned plainBlockSize; | |
93 | ||
94 | /* padding - not present means value zero, CSSM_PADDING_NONE */ | |
95 | uint32 padding = context.getInt(CSSM_ATTRIBUTE_PADDING); | |
96 | switch(padding) { | |
97 | case CSSM_PADDING_NONE: | |
98 | mPadding = RSA_NO_PADDING; | |
99 | plainBlockSize = cipherBlockSize; | |
100 | break; | |
101 | case CSSM_PADDING_PKCS1: | |
102 | mPadding = RSA_PKCS1_PADDING; | |
103 | plainBlockSize = cipherBlockSize - 11; | |
104 | break; | |
105 | case CSSM_PADDING_APPLE_SSLv2: | |
106 | rsaCryptDebug("RSA_CryptContext::init using CSSM_PADDING_APPLE_SSLv2"); | |
107 | mPadding = RSA_SSLV23_PADDING; | |
108 | plainBlockSize = cipherBlockSize - 11; | |
109 | break; | |
110 | default: | |
111 | rsaCryptDebug("RSA_CryptContext::init bad padding (0x%x)", | |
112 | (unsigned)padding); | |
113 | CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING); | |
114 | } | |
115 | ||
116 | /* optional blinding attribute */ | |
117 | uint32 blinding = context.getInt(CSSM_ATTRIBUTE_RSA_BLINDING); | |
118 | if(blinding) { | |
119 | if(RSA_blinding_on(mRsaKey, NULL) <= 0) { | |
120 | /* actually no legit failures */ | |
121 | CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); | |
122 | } | |
123 | } | |
124 | else { | |
125 | RSA_blinding_off(mRsaKey); | |
126 | } | |
127 | ||
128 | /* finally, have BlockCryptor set up its stuff. */ | |
129 | setup(encoding ? plainBlockSize : cipherBlockSize, // blockSizeIn | |
130 | encoding ? cipherBlockSize : plainBlockSize, // blockSizeOut | |
131 | false, // pkcs5Pad | |
132 | false, // needsFinal | |
133 | BCM_ECB, | |
134 | NULL); // IV | |
135 | mInitFlag = true; | |
136 | ||
137 | } | |
138 | /* called by BlockCryptor */ | |
139 | void RSA_CryptContext::encryptBlock( | |
140 | const void *plainText, // length implied (one block) | |
141 | size_t plainTextLen, | |
142 | void *cipherText, | |
143 | size_t &cipherTextLen, // in/out, throws on overflow | |
144 | bool final) | |
145 | { | |
146 | StLock<Mutex> _(gMutex()); | |
147 | ||
148 | int irtn; | |
149 | ||
150 | /* FIXME do OAEP encoding here */ | |
151 | if(mRsaKey->d == NULL) { | |
427c49bc | 152 | irtn = RSA_public_encrypt((int)plainTextLen, |
b1ab9ed8 A |
153 | (unsigned char *)plainText, |
154 | (unsigned char *)cipherText, | |
155 | mRsaKey, | |
156 | mPadding); | |
157 | } | |
158 | else { | |
427c49bc | 159 | irtn = RSA_private_encrypt((int)plainTextLen, |
b1ab9ed8 A |
160 | (unsigned char *)plainText, |
161 | (unsigned char *)cipherText, | |
162 | mRsaKey, | |
163 | mPadding); | |
164 | } | |
165 | if(irtn < 0) { | |
166 | throwRsaDsa("RSA_public_encrypt"); | |
167 | } | |
168 | else if((unsigned)irtn > cipherTextLen) { | |
169 | rsaCryptDebug("RSA_public_encrypt overflow"); | |
170 | CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); | |
171 | } | |
172 | cipherTextLen = (size_t)irtn; | |
173 | } | |
174 | ||
175 | void RSA_CryptContext::decryptBlock( | |
176 | const void *cipherText, // length implied (one cipher block) | |
177 | size_t cipherTextLen, | |
178 | void *plainText, | |
179 | size_t &plainTextLen, // in/out, throws on overflow | |
180 | bool final) | |
181 | { | |
182 | StLock<Mutex> _(gMutex()); | |
183 | ||
184 | int irtn; | |
185 | ||
186 | rsaCryptDebug("decryptBlock padding %d", mPadding); | |
187 | /* FIXME do OAEP encoding here */ | |
188 | if(mRsaKey->d == NULL) { | |
427c49bc | 189 | irtn = RSA_public_decrypt((int)inBlockSize(), |
b1ab9ed8 A |
190 | (unsigned char *)cipherText, |
191 | (unsigned char *)plainText, | |
192 | mRsaKey, | |
193 | mPadding); | |
194 | } | |
195 | else { | |
427c49bc | 196 | irtn = RSA_private_decrypt((int)inBlockSize(), |
b1ab9ed8 A |
197 | (unsigned char *)cipherText, |
198 | (unsigned char *)plainText, | |
199 | mRsaKey, | |
200 | mPadding); | |
201 | } | |
202 | if(irtn < 0) { | |
203 | rsaCryptDebug("decryptBlock err"); | |
204 | throwRsaDsa("RSA_private_decrypt"); | |
205 | } | |
206 | else if((unsigned)irtn > plainTextLen) { | |
207 | rsaCryptDebug("RSA_private_decrypt overflow"); | |
208 | CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); | |
209 | } | |
210 | plainTextLen = (size_t)irtn; | |
211 | } | |
212 | ||
213 | size_t RSA_CryptContext::outputSize( | |
214 | bool final, // ignored | |
215 | size_t inSize /*= 0*/) // output for given input size | |
216 | { | |
217 | StLock<Mutex> _(gMutex()); | |
218 | ||
427c49bc A |
219 | size_t rawBytes = inSize + inBufSize(); |
220 | size_t rawBlocks = (rawBytes + inBlockSize() - 1) / inBlockSize(); | |
221 | rbprintf("--- RSA_CryptContext::outputSize inSize 0x%lux outSize 0x%lux mInBufSize 0x%lux", | |
222 | (unsigned long)inSize, (unsigned long)(rawBlocks * outBlockSize()), (unsigned long)inBufSize()); | |
b1ab9ed8 A |
223 | return rawBlocks * outBlockSize(); |
224 | } |