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
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
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
43 CMSG_STREAM_INFO stream_info
;
45 CryptMsgCloseFunc close
;
46 CryptMsgUpdateFunc update
;
47 CryptMsgGetParamFunc get_param
;
50 static inline void CryptMsgBase_Init(CryptMsgBase
*msg
, DWORD dwFlags
,
51 PCMSG_STREAM_INFO pStreamInfo
, CryptMsgCloseFunc close
,
52 CryptMsgGetParamFunc get_param
, CryptMsgUpdateFunc update
)
55 msg
->open_flags
= dwFlags
;
59 memcpy(&msg
->stream_info
, pStreamInfo
, sizeof(msg
->stream_info
));
63 msg
->streamed
= FALSE
;
64 memset(&msg
->stream_info
, 0, sizeof(msg
->stream_info
));
67 msg
->get_param
= get_param
;
69 msg
->finalized
= FALSE
;
72 typedef struct _CDataEncodeMsg
75 DWORD bare_content_len
;
79 static const BYTE empty_data_content
[] = { 0x04,0x00 };
81 static void CDataEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
83 CDataEncodeMsg
*msg
= (CDataEncodeMsg
*)hCryptMsg
;
85 if (msg
->bare_content
!= empty_data_content
)
86 LocalFree(msg
->bare_content
);
89 static BOOL
CDataEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
90 DWORD cbData
, BOOL fFinal
)
92 CDataEncodeMsg
*msg
= (CDataEncodeMsg
*)hCryptMsg
;
95 if (msg
->base
.finalized
)
96 SetLastError(CRYPT_E_MSG_ERROR
);
99 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
100 SetLastError(E_INVALIDARG
);
102 SetLastError(CRYPT_E_MSG_ERROR
);
106 msg
->base
.finalized
= TRUE
;
108 SetLastError(E_INVALIDARG
);
111 CRYPT_DATA_BLOB blob
= { cbData
, (LPBYTE
)pbData
};
113 /* data messages don't allow non-final updates, don't bother
114 * checking whether data already exist, they can't.
116 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
117 &blob
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &msg
->bare_content
,
118 &msg
->bare_content_len
);
119 if (ret
&& msg
->base
.streamed
)
120 FIXME("stream info unimplemented\n");
126 static BOOL
CDataEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
127 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
129 CDataEncodeMsg
*msg
= (CDataEncodeMsg
*)hCryptMsg
;
134 case CMSG_CONTENT_PARAM
:
136 CRYPT_CONTENT_INFO info
;
137 char rsa_data
[] = "1.2.840.113549.1.7.1";
139 info
.pszObjId
= rsa_data
;
140 info
.Content
.cbData
= msg
->bare_content_len
;
141 info
.Content
.pbData
= msg
->bare_content
;
142 ret
= CryptEncodeObject(X509_ASN_ENCODING
, PKCS_CONTENT_INFO
, &info
,
146 case CMSG_BARE_CONTENT_PARAM
:
149 *pcbData
= msg
->bare_content_len
;
152 else if (*pcbData
< msg
->bare_content_len
)
154 *pcbData
= msg
->bare_content_len
;
155 SetLastError(ERROR_MORE_DATA
);
159 *pcbData
= msg
->bare_content_len
;
160 memcpy(pvData
, msg
->bare_content
, msg
->bare_content_len
);
165 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
170 static HCRYPTMSG
CDataEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
171 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
177 SetLastError(E_INVALIDARG
);
180 msg
= CryptMemAlloc(sizeof(CDataEncodeMsg
));
183 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
,
184 CDataEncodeMsg_Close
, CDataEncodeMsg_GetParam
, CDataEncodeMsg_Update
);
185 msg
->bare_content_len
= sizeof(empty_data_content
);
186 msg
->bare_content
= (LPBYTE
)empty_data_content
;
188 return (HCRYPTMSG
)msg
;
191 static inline const char *MSG_TYPE_STR(DWORD type
)
195 #define _x(x) case (x): return #x
199 _x(CMSG_SIGNED_AND_ENVELOPED
);
204 return wine_dbg_sprintf("unknown (%d)", type
);
208 HCRYPTMSG WINAPI
CryptMsgOpenToEncode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
209 DWORD dwMsgType
, const void *pvMsgEncodeInfo
, LPSTR pszInnerContentObjID
,
210 PCMSG_STREAM_INFO pStreamInfo
)
212 HCRYPTMSG msg
= NULL
;
214 TRACE("(%08x, %08x, %08x, %p, %s, %p)\n", dwMsgEncodingType
, dwFlags
,
215 dwMsgType
, pvMsgEncodeInfo
, debugstr_a(pszInnerContentObjID
), pStreamInfo
);
217 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
219 SetLastError(E_INVALIDARG
);
225 msg
= CDataEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
226 pszInnerContentObjID
, pStreamInfo
);
231 FIXME("unimplemented for type %s\n", MSG_TYPE_STR(dwMsgType
));
233 case CMSG_SIGNED_AND_ENVELOPED
:
235 /* defined but invalid, fall through */
237 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
242 HCRYPTMSG WINAPI
CryptMsgOpenToDecode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
243 DWORD dwMsgType
, HCRYPTPROV hCryptProv
, PCERT_INFO pRecipientInfo
,
244 PCMSG_STREAM_INFO pStreamInfo
)
246 FIXME("(%08x, %08x, %08x, %08lx, %p, %p): stub\n", dwMsgEncodingType
,
247 dwFlags
, dwMsgType
, hCryptProv
, pRecipientInfo
, pStreamInfo
);
249 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
251 SetLastError(E_INVALIDARG
);
257 HCRYPTMSG WINAPI
CryptMsgDuplicate(HCRYPTMSG hCryptMsg
)
259 TRACE("(%p)\n", hCryptMsg
);
263 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
265 InterlockedIncrement(&msg
->ref
);
270 BOOL WINAPI
CryptMsgClose(HCRYPTMSG hCryptMsg
)
272 TRACE("(%p)\n", hCryptMsg
);
276 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
278 if (InterlockedDecrement(&msg
->ref
) == 0)
280 TRACE("freeing %p\n", msg
);
289 BOOL WINAPI
CryptMsgUpdate(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
290 DWORD cbData
, BOOL fFinal
)
292 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
295 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
296 if (msg
&& msg
->update
)
297 ret
= msg
->update(hCryptMsg
, pbData
, cbData
, fFinal
);
301 BOOL WINAPI
CryptMsgGetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
302 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
304 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
307 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
309 if (msg
&& msg
->get_param
)
310 ret
= msg
->get_param(hCryptMsg
, dwParamType
, dwIndex
, pvData
, pcbData
);