Example #1
0
// OpenToEncode creates new Msg in encode mode.
func OpenToEncode(dest io.Writer, options EncodeOptions) (res *Msg, err error) {
	var flags C.DWORD

	res = new(Msg)

	if len(options.Signers) == 0 {
		err = fmt.Errorf("Signer certificates list is empty")
		return
	}
	if options.HashAlg == nil {
		options.HashAlg = GOST_R3411
	}
	if options.Detached {
		flags = C.CMSG_DETACHED_FLAG
	}

	si := C.mkStreamInfo(unsafe.Pointer(res))
	defer C.free(unsafe.Pointer(si))

	signedInfo := C.mkSignedInfo(C.int(len(options.Signers)))
	defer C.freeSignedInfo(signedInfo)

	hashOID := C.CString(options.HashAlg.String())
	defer C.free(unsafe.Pointer(hashOID))

	for i, signerCert := range options.Signers {
		var (
			hCryptProv C.HCRYPTPROV
			dwKeySpec  C.DWORD
		)
		if 0 == C.CryptAcquireCertificatePrivateKey(signerCert.pCert, 0, nil, &hCryptProv, &dwKeySpec, nil) {
			err = getErr("Error acquiring certificate private key")
			return
		}
		C.setSignedInfo(signedInfo, C.int(i), hCryptProv, signerCert.pCert, dwKeySpec, (*C.CHAR)(hashOID))
	}

	res.hMsg = C.CryptMsgOpenToEncode(
		C.MY_ENC_TYPE,              // encoding type
		flags,                      // flags
		C.CMSG_SIGNED,              // message type
		unsafe.Pointer(signedInfo), // pointer to structure
		nil, // inner content OID
		si,  // stream information
	)
	if res.hMsg == nil {
		err = getErr("Error opening message for encoding")
		return
	}
	res.dest = dest
	res.updateCallback = res.onEncode
	return
}
Example #2
0
// OpenToDecode creates new Msg in decode mode. If detachedSig parameter is specified,
// it must contain detached P7S signature
func OpenToDecode(src io.Reader, detachedSig ...[]byte) (res *Msg, err error) {
	var (
		flags C.DWORD
		si    *C.CMSG_STREAM_INFO
	)
	res = new(Msg)

	if len(detachedSig) > 0 {
		flags = C.CMSG_DETACHED_FLAG
		si = nil
	} else {
		si = C.mkStreamInfo(unsafe.Pointer(res))
		defer C.free(unsafe.Pointer(si))
	}
	res.hMsg = C.CryptMsgOpenToDecode(
		C.MY_ENC_TYPE, // encoding type
		flags,         // flags
		0,             // message type (get from message)
		0,             // default cryptographic provider
		nil,           // recipient information
		si,            // stream info
	)
	if res.hMsg == nil {
		err = getErr("Error opening message for decoding")
		return
	}
	res.src = src
	res.updateCallback = res.onDecode
	for i, p := range detachedSig {
		if !res.update(p, len(p), i == len(detachedSig)-1) {
			err = getErr("Error updating message header")
			return
		}
	}
	return
}