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
42 PCMSG_STREAM_INFO stream_info
;
44 CryptMsgCloseFunc close
;
45 CryptMsgUpdateFunc update
;
46 CryptMsgGetParamFunc get_param
;
49 static inline void CryptMsgBase_Init(CryptMsgBase
*msg
, DWORD dwFlags
,
50 PCMSG_STREAM_INFO pStreamInfo
)
53 msg
->open_flags
= dwFlags
;
54 msg
->stream_info
= pStreamInfo
;
55 msg
->finalized
= FALSE
;
58 typedef struct _CDataEncodeMsg
61 DWORD bare_content_len
;
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
;
81 if (msg
->base
.finalized
)
82 SetLastError(CRYPT_E_MSG_ERROR
);
85 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
86 SetLastError(E_INVALIDARG
);
88 SetLastError(CRYPT_E_MSG_ERROR
);
92 msg
->base
.finalized
= TRUE
;
94 SetLastError(E_INVALIDARG
);
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");
112 static BOOL
CDataEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
113 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
115 CDataEncodeMsg
*msg
= (CDataEncodeMsg
*)hCryptMsg
;
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
,
132 case CMSG_BARE_CONTENT_PARAM
:
135 *pcbData
= msg
->bare_content_len
;
138 else if (*pcbData
< msg
->bare_content_len
)
140 *pcbData
= msg
->bare_content_len
;
141 SetLastError(ERROR_MORE_DATA
);
145 *pcbData
= msg
->bare_content_len
;
146 memcpy(pvData
, msg
->bare_content
, msg
->bare_content_len
);
151 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
156 static HCRYPTMSG
CDataEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
157 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
163 SetLastError(E_INVALIDARG
);
166 msg
= CryptMemAlloc(sizeof(CDataEncodeMsg
));
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
)
183 #define _x(x) case (x): return #x
187 _x(CMSG_SIGNED_AND_ENVELOPED
);
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
);
213 msg
= CDataEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
214 pszInnerContentObjID
, pStreamInfo
);
219 FIXME("unimplemented for type %s\n", MSG_TYPE_STR(dwMsgType
));
221 case CMSG_SIGNED_AND_ENVELOPED
:
223 /* defined but invalid, fall through */
225 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
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
);
245 HCRYPTMSG WINAPI
CryptMsgDuplicate(HCRYPTMSG hCryptMsg
)
247 TRACE("(%p)\n", hCryptMsg
);
251 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
253 InterlockedIncrement(&msg
->ref
);
258 BOOL WINAPI
CryptMsgClose(HCRYPTMSG hCryptMsg
)
260 TRACE("(%p)\n", hCryptMsg
);
264 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
266 if (InterlockedDecrement(&msg
->ref
) == 0)
268 TRACE("freeing %p\n", msg
);
277 BOOL WINAPI
CryptMsgUpdate(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
278 DWORD cbData
, BOOL fFinal
)
280 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
283 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
284 if (msg
&& msg
->update
)
285 ret
= msg
->update(hCryptMsg
, pbData
, cbData
, fFinal
);
289 BOOL WINAPI
CryptMsgGetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
290 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
292 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
295 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
297 if (msg
&& msg
->get_param
)
298 ret
= msg
->get_param(hCryptMsg
, dwParamType
, dwIndex
, pvData
, pcbData
);