push aea352fc3df615e3f4b48daf6f897ea93ad1fffd
[wine/hacks.git] / dlls / crypt32 / msg.c
blob4ac5cf09856a21f4774bb891e245cdb59296361d
1 /*
2 * Copyright 2007 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 #include <stdarg.h>
19 #include "windef.h"
20 #include "winbase.h"
21 #include "wincrypt.h"
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
27 /* Called when a message's ref count reaches zero. Free any message-specific
28 * data here.
30 typedef void (*CryptMsgCloseFunc)(HCRYPTMSG msg);
32 typedef BOOL (*CryptMsgGetParamFunc)(HCRYPTMSG hCryptMsg, DWORD dwParamType,
33 DWORD dwIndex, void *pvData, DWORD *pcbData);
35 typedef BOOL (*CryptMsgUpdateFunc)(HCRYPTMSG hCryptMsg, const BYTE *pbData,
36 DWORD cbData, BOOL fFinal);
38 typedef struct _CryptMsgBase
40 LONG ref;
41 DWORD open_flags;
42 PCMSG_STREAM_INFO stream_info;
43 BOOL finalized;
44 CryptMsgCloseFunc close;
45 CryptMsgUpdateFunc update;
46 CryptMsgGetParamFunc get_param;
47 } CryptMsgBase;
49 static inline void CryptMsgBase_Init(CryptMsgBase *msg, DWORD dwFlags,
50 PCMSG_STREAM_INFO pStreamInfo)
52 msg->ref = 1;
53 msg->open_flags = dwFlags;
54 msg->stream_info = pStreamInfo;
55 msg->finalized = FALSE;
58 typedef struct _CDataEncodeMsg
60 CryptMsgBase base;
61 DWORD bare_content_len;
62 LPBYTE bare_content;
63 } CDataEncodeMsg;
65 static const BYTE empty_data_content[] = { 0x04,0x00 };
67 static void CDataEncodeMsg_Close(HCRYPTMSG hCryptMsg)
69 CDataEncodeMsg *msg = (CDataEncodeMsg *)hCryptMsg;
71 if (msg->bare_content != empty_data_content)
72 LocalFree(msg->bare_content);
75 static BOOL CDataEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData,
76 DWORD cbData, BOOL fFinal)
78 CDataEncodeMsg *msg = (CDataEncodeMsg *)hCryptMsg;
79 BOOL ret = FALSE;
81 if (msg->base.finalized)
82 SetLastError(CRYPT_E_MSG_ERROR);
83 else if (!fFinal)
85 if (msg->base.open_flags & CMSG_DETACHED_FLAG)
86 SetLastError(E_INVALIDARG);
87 else
88 SetLastError(CRYPT_E_MSG_ERROR);
90 else
92 msg->base.finalized = TRUE;
93 if (!cbData)
94 SetLastError(E_INVALIDARG);
95 else
97 CRYPT_DATA_BLOB blob = { cbData, (LPBYTE)pbData };
99 /* data messages don't allow non-final updates, don't bother
100 * checking whether data already exist, they can't.
102 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING,
103 &blob, CRYPT_ENCODE_ALLOC_FLAG, NULL, &msg->bare_content,
104 &msg->bare_content_len);
105 if (ret && msg->base.stream_info)
106 FIXME("stream info unimplemented\n");
109 return ret;
112 static BOOL CDataEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType,
113 DWORD dwIndex, void *pvData, DWORD *pcbData)
115 CDataEncodeMsg *msg = (CDataEncodeMsg *)hCryptMsg;
116 BOOL ret = FALSE;
118 switch (dwParamType)
120 case CMSG_CONTENT_PARAM:
122 CRYPT_CONTENT_INFO info;
123 char rsa_data[] = "1.2.840.113549.1.7.1";
125 info.pszObjId = rsa_data;
126 info.Content.cbData = msg->bare_content_len;
127 info.Content.pbData = msg->bare_content;
128 ret = CryptEncodeObject(X509_ASN_ENCODING, PKCS_CONTENT_INFO, &info,
129 pvData, pcbData);
130 break;
132 case CMSG_BARE_CONTENT_PARAM:
133 if (!pvData)
135 *pcbData = msg->bare_content_len;
136 ret = TRUE;
138 else if (*pcbData < msg->bare_content_len)
140 *pcbData = msg->bare_content_len;
141 SetLastError(ERROR_MORE_DATA);
143 else
145 *pcbData = msg->bare_content_len;
146 memcpy(pvData, msg->bare_content, msg->bare_content_len);
147 ret = TRUE;
149 break;
150 default:
151 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
153 return ret;
156 static HCRYPTMSG CDataEncodeMsg_Open(DWORD dwFlags, const void *pvMsgEncodeInfo,
157 LPSTR pszInnerContentObjID, PCMSG_STREAM_INFO pStreamInfo)
159 CDataEncodeMsg *msg;
161 if (pvMsgEncodeInfo)
163 SetLastError(E_INVALIDARG);
164 return NULL;
166 msg = CryptMemAlloc(sizeof(CDataEncodeMsg));
167 if (msg)
169 CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo);
170 msg->base.close = CDataEncodeMsg_Close;
171 msg->base.update = CDataEncodeMsg_Update;
172 msg->base.get_param = CDataEncodeMsg_GetParam;
173 msg->bare_content_len = sizeof(empty_data_content);
174 msg->bare_content = (LPBYTE)empty_data_content;
176 return (HCRYPTMSG)msg;
179 static inline const char *MSG_TYPE_STR(DWORD type)
181 switch (type)
183 #define _x(x) case (x): return #x
184 _x(CMSG_DATA);
185 _x(CMSG_SIGNED);
186 _x(CMSG_ENVELOPED);
187 _x(CMSG_SIGNED_AND_ENVELOPED);
188 _x(CMSG_HASHED);
189 _x(CMSG_ENCRYPTED);
190 #undef _x
191 default:
192 return wine_dbg_sprintf("unknown (%d)", type);
196 HCRYPTMSG WINAPI CryptMsgOpenToEncode(DWORD dwMsgEncodingType, DWORD dwFlags,
197 DWORD dwMsgType, const void *pvMsgEncodeInfo, LPSTR pszInnerContentObjID,
198 PCMSG_STREAM_INFO pStreamInfo)
200 HCRYPTMSG msg = NULL;
202 TRACE("(%08x, %08x, %08x, %p, %s, %p)\n", dwMsgEncodingType, dwFlags,
203 dwMsgType, pvMsgEncodeInfo, debugstr_a(pszInnerContentObjID), pStreamInfo);
205 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType) != PKCS_7_ASN_ENCODING)
207 SetLastError(E_INVALIDARG);
208 return NULL;
210 switch (dwMsgType)
212 case CMSG_DATA:
213 msg = CDataEncodeMsg_Open(dwFlags, pvMsgEncodeInfo,
214 pszInnerContentObjID, pStreamInfo);
215 break;
216 case CMSG_SIGNED:
217 case CMSG_ENVELOPED:
218 case CMSG_HASHED:
219 FIXME("unimplemented for type %s\n", MSG_TYPE_STR(dwMsgType));
220 break;
221 case CMSG_SIGNED_AND_ENVELOPED:
222 case CMSG_ENCRYPTED:
223 /* defined but invalid, fall through */
224 default:
225 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
227 return msg;
230 HCRYPTMSG WINAPI CryptMsgOpenToDecode(DWORD dwMsgEncodingType, DWORD dwFlags,
231 DWORD dwMsgType, HCRYPTPROV hCryptProv, PCERT_INFO pRecipientInfo,
232 PCMSG_STREAM_INFO pStreamInfo)
234 FIXME("(%08x, %08x, %08x, %08lx, %p, %p): stub\n", dwMsgEncodingType,
235 dwFlags, dwMsgType, hCryptProv, pRecipientInfo, pStreamInfo);
237 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType) != PKCS_7_ASN_ENCODING)
239 SetLastError(E_INVALIDARG);
240 return NULL;
242 return NULL;
245 HCRYPTMSG WINAPI CryptMsgDuplicate(HCRYPTMSG hCryptMsg)
247 TRACE("(%p)\n", hCryptMsg);
249 if (hCryptMsg)
251 CryptMsgBase *msg = (CryptMsgBase *)hCryptMsg;
253 InterlockedIncrement(&msg->ref);
255 return hCryptMsg;
258 BOOL WINAPI CryptMsgClose(HCRYPTMSG hCryptMsg)
260 TRACE("(%p)\n", hCryptMsg);
262 if (hCryptMsg)
264 CryptMsgBase *msg = (CryptMsgBase *)hCryptMsg;
266 if (InterlockedDecrement(&msg->ref) == 0)
268 TRACE("freeing %p\n", msg);
269 if (msg->close)
270 msg->close(msg);
271 CryptMemFree(msg);
274 return TRUE;
277 BOOL WINAPI CryptMsgUpdate(HCRYPTMSG hCryptMsg, const BYTE *pbData,
278 DWORD cbData, BOOL fFinal)
280 CryptMsgBase *msg = (CryptMsgBase *)hCryptMsg;
281 BOOL ret = FALSE;
283 TRACE("(%p, %p, %d, %d)\n", hCryptMsg, pbData, cbData, fFinal);
284 if (msg && msg->update)
285 ret = msg->update(hCryptMsg, pbData, cbData, fFinal);
286 return ret;
289 BOOL WINAPI CryptMsgGetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType,
290 DWORD dwIndex, void *pvData, DWORD *pcbData)
292 CryptMsgBase *msg = (CryptMsgBase *)hCryptMsg;
293 BOOL ret = FALSE;
295 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg, dwParamType, dwIndex,
296 pvData, pcbData);
297 if (msg && msg->get_param)
298 ret = msg->get_param(hCryptMsg, dwParamType, dwIndex, pvData, pcbData);
299 return ret;