MS OPM (Output Protection Manager) Initializing X509 chain - c++

I trying to OPM (Output Protection Manager) with Visual C++ (native) using
OPMAPI. My goal is enable HDCP session between HDMI device driver and display to protect contents through out HDMI cable.
I got an example from MSDN
In example code there's some undocumented function about certifications.
(ValidateX509Certificate, GetPublicKeyFromCertificate)
Here follows example code.
OPM_RANDOM_NUMBER random; // Random number from driver.
ZeroMemory(&random, sizeof(random));
BYTE *pbCertificate = NULL; // Pointer to a buffer to hold the certificate.
ULONG cbCertificate = 0; // Size of the certificate in bytes.
PUBLIC_KEY_VALUES *pKey = NULL; // The driver's public key.
// Get the driver's certificate chain + random number
HRESULT hr = pVideoOutput->StartInitialization(
&random,
&pbCertificate,
&cbCertificate );
// Validate the X.509 certificate. (Not shown.)
hr = ValidateX509Certificate(pbCertificate, cbCertificate);
if (FAILED(hr))
{
goto done;
}
// Get the public key from the certificate. (Not shown.)
hr = GetPublicKeyFromCertificate(
pbCertificate,
cbCertificate,
&pKey );
According to MSDN, IOPMVideoOutput::StartInitialization() retrieves random number and X509 certificate chain (pbCertificate).
ValidateX509Certificate() and GetPublicKeyFromCertificate() function are not shown.
Could anyone explain to me the way to write above two function please?
Or I want to know how decode X.509 cert chain data (DER) into CERT_CHAIN_CONTEXT.

The StartInitialization function returns the complete certificate chain of the driver as signed PKCS7 data with DER encoding. This is not the usual X509 certificate with DER encoding we commonly deal with. Unfortunately this is not mentioned in the MSDN pages.
The certificates/certificate chain can be extracted from signed PKCS7 DER using any crypto library/framework. We can verify and get the public key using Microsoft crypto framework with the folloing steps.
Get certificate chain with CryptGetMessageCertificates function
Optionally you can verify the certificate chain as explained "Performing X.509 Certificate Verification with CryptoAPI"
Get the subject certificate CERT_CONTEXT as explained in Step 2. The subject public key can be retrieved from pCertInfo of CERT_CONTEXT.
It is much easier (at least I feel like) to do with OpenSSL which is explained "how to Read the certificates file from the PKCS7.p7b certificate file usind openssl". It shows how to retrieve the certificates and you can easily retrieve public key using X509_get_pubkey function.

Here is a sample code to implement the missed function mentioned MSDN, and show how to use OPM and the related crypto implementation based on the standard window API, https://github.com/wangf1978/D3DTest, CryptoUtil.cpp/OPMSession.cpp

Related

EPP Server SSL_Read hang after greeting

I have strange problems in ssl_read/ssl_write function with EPP server
After connected I read greeting message successfully.
bytes = SSL_read(ssl, buf, sizeof(buf)); // get reply & decrypt
buf[bytes] = 0;
ball+= bytes;
cc = getInt(buf);
printf("header: %x\n",cc);
printf("Received: \"%s\"\n",buf+4);
First 4 bytes are 00, 00, 09, EB and read 2539 bytes in greeting message.
After that, all operations like hello or logins are hand when SSL_read();
xml= "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><eppxmlns=\"urn:ietf:params:xml:ns:epp-1.0\"><hello/></epp>";
char bb[1000] = {0};
makeChar(strlen(xml)+4, bb);
memcpy(bb+4, xml, strlen(xml)+4);
bytes = SSL_write(ssl,xml,strlen(xml)+4);
usleep(500000); //sleep 0.5 sec
memset(buf, 0, 1024);
printf("read starting.\n");
bytes = SSL_read(ssl, buf, 1024); //always hang here
buf[bytes]=0;
printf("%d : %s", bytes, buf);
I am confused. I read RFC documentations but I can not find answer.
in EPP documentation, they said "In order to verify the identity of the secure server you will need the ‘Verisign Class 3 Public Primary Certification Authority’ root certificate available free from www.verisign.com".
is it important?
is it important?
Yes, as outlined in RFC 5734 "Extensible Provisioning Protocol (EPP) Transport over TCP", the whole security of an EPP exchange is bound to 3 properties:
access list based on IP address
TLS communication and verification of certificates (mutually, which is why you - as registrar aka client in EPP communication - have often to send in advance the certificate you will use ot the registry)
the EPP credentials used at <login> command.
Failure to properly secure the connection can mean:
you as registrar sending confidential information (your own EPP login, various details on domains you sponsor or not, including <authInfo> values, etc.) to a third party not being the registry
and in reverse, someone mimicking you in the eyes of the registry hence doing operations on which you will have to get the burden of, including financially for all domains bought, and legally.
But even in general for all cases of TLS handshake, if you want to be sure to be connected, as client, to the server you think you are, you need to verify its certificate.
Besides trivial things (dates, etc.), the certificate:
should at least be signed by an AC you trust (your choice who you trust)
and/or is a specific certificate with specific fingerprint/serial and other characteristics (but you will have to maintain that when the other party changes its certificate)
and/or matches DNS TLSA records
In short, if you are new to both EPP and TLS and C/C++ (as you state yourself in your other question about Verisign certificate), I hugely recommend you do not try to do all of this by yourself at a so low level (for example you should never manipulate XML as you do above, it shouldn't be a string. Again, there are libraries to properly parse and generate XML documents). You should use an EPP library that leverage most of the things for you. Your registry may provide an "SDK" that you can use, you should ask it.
PS: your read is probably hanging because you are not sending the payload in the correct fashion (again, something an EPP library will do for you). You need to send the length, as 4 bytes (which you need to compute after converting your string to bytes using the UTF-8 encoding), and then the payload itself. I am not sure this is what your code does. Also your reading part is wrong: you should first read 4 bytes from server, this will give you the length (but do note they can theoretically arrive not necessarily in a single packet so one "ssl read" might not give all 4 of them, you need a loop), after which you know the length of the payload you will get which allows you to set up proper buffers, if needed, as well as detecting properly when you received everything.

Service Discovery Protocol: Check for multiple Services at once

I followed the instructions on https://people.csail.mit.edu/albert/bluez-intro/x604.html to check for a specified Bluetooth service of a device. I can succesfully check for the Serial Port Profile.
From Bluetooth traces, I noticed that some devices search for multiple services at the same time. Is it possible to extend the source code from the website mentioned above to get this functionality? I tried
[...]
search_list = sdp_list_append( NULL, &svc_uuid_1 );
search_list = sdp_list_append( NULL, &svc_uuid_2 );
[...]
but this seems not to work, it does not really 'append' the UUID in the search_list but does overwrite it.
Moreover, the traces show that one single SDP request does cover SPP, RFCOMM and L2CAP. Can profiles and protocols be mixed in SDP request?
Additionally, I'm confused by the following snippet, also from website above:
// specify that we want a list of all the matching applications' attributes
uint32_t range = 0x0000ffff;
attrid_list = sdp_list_append( NULL, &range );
What exactly is range? What options does it offer? Unfortunately, I couldn't find any explanations in Bluetooth core documentation v4.2.

gsoap Reading CA file, Windows

I am trying to consume a webservice that I created and deployed in tomcat, enabling ssl in this latter.
For creating the client code, I use gsoap. I generated nedded files, and below my code in C++ :
soap_ssl_init();
soap_init(&soap);
if (soap_ssl_client_context(&soap,
SOAP_SSL_DEFAULT, /* use SOAP_SSL_DEFAULT in production code */
NULL, /* keyfile: required only when client must authenticate to server (see SSL docs on how to obtain this file) */
NULL, /* password to read the keyfile */
"cacert.pem", /* optional cacert file to store trusted certificates */
NULL, /* optional capath to directory with trusted certificates */
NULL /* if randfile!=NULL: use a file with random data to seed randomness */
))
{
soap_print_fault(&soap, stderr);
exit(1);
}
if(soap_call___ns2__Add(&soap,"https://localhost:8443/TestWebService/services/AddService.AddServiceHttpsSoap11Endpoint", NULL,&add, &resp)!= 0)
soap_print_fault(&soap, stderr);
When I execute the program, I got this meesage :
Error 30 fault: SOAP-ENV:Server [no subcode] "SSL error" Detail: Can't
read CA file and directory
As I read, I thinh that I have to generate some files (.pem, certs...).
It's the first time that I use goap and ssl, How could I solve this issue?
I use Windows (coz all examples that I found are for linux)
The problem was not related to my C++ Client code. Infact, I had to add the server certification file to the Bin\security\cacerts file located into my jre.
I had to try to implement a Java client to understand the problem.

Play Framework 2.3 WS SSL Disable AlgorithmChecker

I'm currently trying to use WS in Play 2.3 to interact with the Visa Direct Payments API but I am struggling as the sandbox key provided is RSA has a key size of 1024 and, from what I've read in the source code comments, is considered not safe so is disabled.
As this is just sandbox I would like to know if there is a way to disable this extra key checking, I have already tried ws.acceptAnyCertificate=true without any luck.
The errors I am recieving in the console are as follows:
[warn] p.a.l.w.s.ConfigSSLContextBuilder - validateKeyStore: Skipping certificate with weak key size in visasandboxcert: Certificate failed: cert = "CN=841edac8-d8cd-4593-b575-fdf3bbee5e67,OU=VMT,O=Visa,L=Foster City,ST=CA,C=US" failed on constraint RSA keySize < 2048, algorithm = RSA, keySize = 1024
[error] play - Cannot invoke the action, eventually got an error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
Can anyone give me any advice how I can get round this? Preferably without changing the Play source code and building from that.
First, you need to talk to Visa Direct Payments and file a bug report letting them know that a 1024 bit key is utterly unacceptable in this day and age.
Second, you need to set:
ws.ssl.disabledKeyAlgorithms="RSA keySize < 1024"
which will tell the Algorithms checker to ease up. See Certificate Validation for more details.
if you are using play 2.6.x, you can do it this way
play.ws {
ssl {
debug.handshake = true
disabledKeyAlgorithms =["RSA keySize < 1024"]
}
}

Extracting modulus and exponent from public key using Openssl and C++

So I'm currently studying how networking works. I've got a bunch of packets from wireshark which I have already copied in buffers(only the content, without header. Wireshark->Follow TPC Stream->C arrays). I can understand the protocol but in the 3rd packet it requires a key exchange. After some googling I found that I need RSA encryption. It sends me a public key + token. And I shoud return encrypted shared key(just generated) and encrypted token which I received earlier.
RSA_key needs exponent and modulus, So my question is: How can I create RSA_key object from single char[] buffer(the public key).
NOTE:I'm posting here after long time googling. I may not be using the right keywords because I'm not english speaker. I could find threads asking this with php only.
The most useful (I think) link I found is http://www.techper.net/2012/06/01/converting-rsa-public-key-modulus-and-exponent-into-pem-file/
Thanks.
P.S. I'm sniffing minecraft and simulating client side(I choosed it because its popular game and I knew I will find resources on the web if I get stuck). However my question is exacly how to get modulus and exponent from a public key with format: http://pastebin.com/J9ddhgW5 (thats the bytes representing the public key)
Ohh I forgot, first column is the byte position, second column is the byte value typecasted to int, 3th column is again value but (int)(unsigned char) so I can see if its +127, 4th colums is the hex representation of the value and the last column is character based on ascii table(if its visible character).
The data you posted is an ASN.1 encoded (DER) RSA public key:
$ openssl ssl rsa -inform der -pubin -text < 12120862.key
Public-Key: (1024 bit)
Modulus:
00:81:1f:1d:00:7e:d0:c7:e2:2f:31:3d:0d:f0:a8:
ab:c1:ea:66:ba:af:1d:a4:eb:b3:fd:51:58:1c:1d:
81:ae:f0:99:9e:5c:26:67:b5:41:14:28:79:c0:29:
e5:56:96:06:b7:4b:a0:c9:7f:41:46:9a:7e:85:10:
a0:91:ea:58:bd:78:78:6d:3c:07:2a:3d:61:f3:ed:
42:8b:1e:dc:6d:2d:21:41:7a:e8:15:51:0d:75:84:
be:20:8c:76:43:8b:4b:67:6b:49:09:e9:20:a1:11:
53:a0:d9:30:b1:c2:27:a6:09:e1:56:36:ed:7e:9b:
23:e2:df:5b:bd:c5:66:ca:c5
Exponent: 65537 (0x10001)
writing RSA key
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCBHx0AftDH4i8xPQ3wqKvB6ma6
rx2k67P9UVgcHYGu8JmeXCZntUEUKHnAKeVWlga3S6DJf0FGmn6FEKCR6li9eHht
PAcqPWHz7UKLHtxtLSFBeugVUQ11hL4gjHZDi0tna0kJ6SChEVOg2TCxwiemCeFW
Nu1+myPi31u9xWbKxQIDAQAB
-----END PUBLIC KEY-----
In OpenSSL, you can use the d2i_RSA_PUBKEY function to get a public key from an ASN.1-encoded file (like this one).