OpenSSL GCM Encryption using 16-byte IV - c++

In reference to the github project:
https://github.com/majek/openssl/blob/master/demos/evp/aesgcm.c
And another StackOverflow question:
Unable to set IV for aes gcm using openssl
I'm attempting to use OpenSSL to perform GCM encryption with a 128-bit IV. The default IV is 96-bits, 12 bytes. When I set this to 16-bits the value isn't updated and as a result the encrypted data and IV or not correct.
I tried verifying this using the following function which reads back a value of 12, when I was expecting it to change to 16 after setting it via the second following function:
int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx)
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL);
And help with be awesome! Thanks!
Chris

Related

Double AES encryption with random key generation

I am using 2 embedded GSM devices. There needs to send data between devices. Suppose I require to send the string "ring" from one device to another. It is a command and needs to be sent multiple times. 1st thing I do is keep the aes_key same in both devices. Then encrypt the input_data(that is "boom") and get the enc_buffer. Send this enc_buffer over socket to other device. The other device has same aes_key. Using that I decrypt the buffer received into dec_buffer. My doubt is that will the encrypted message enc_buffer be same every time I send the encrypted text for "boom". If it is same, then I need to follow another approach. I have a 1st level aes_key, that is constant. Then I need to generate a 2nd level aes_key. Encrypt the 2nd level aes_key and send it over socket. In the receiving device, decrypt it using 1st level aes_key to get the 2nd level aes_key. Store it. In 1st device again encrypt string "boom" using 2nd level aes_key, send it over socket. In the 2nd device decrypt the encrypted message using 2nd level aes_key to get text "boom". But another problem is how to generate the 2nd level aes_key in 1st device. Is there some random key generator API present in Linux. Or can I use random number generator API. I need a 10 character-length key. For that I call random number generator 10 times to generate a number between 0-26 and convert this to character. Then gather then together to get the desired key. I am using the AES code sample as below. Pasted for reference to above text.
unsigned char aes_key[]= "asytfuhcilejnco";
unsigned char input_data[]= "Sandeep";
int data_size= strlen((char*)input_data);
int buffer_size = ((int)(data_size/AES_BLOCK_SIZE) + 1)*AES_BLOCK_SIZE;
AES_KEY enc_key,dec_key;
unsigned char iv[AES_BLOCK_SIZE];
int main()
{
unsigned char enc_buffer[buffer_size+1];
unsigned char dec_buffer[buffer_size+1];
memset(iv,0x00,AES_BLOCK_SIZE);
AES_set_encrypt_key(aes_key,sizeof(aes_key)*8,&enc_key);
AES_cbc_encrypt(input_data,enc_buffer,sizeof(input_data),&enc_key,iv,AES_ENCRYPT);
enc_buffer[buffer_size+1]='\0';
memset(iv,0x00,AES_BLOCK_SIZE);
AES_set_decrypt_key(aes_key,sizeof(aes_key)*8,&dec_key);
AES_cbc_encrypt(enc_buffer,dec_buffer,sizeof(input_data),&dec_key,iv,AES_DECRYPT);
dec_buffer[buffer_size+1]='\0';
cout<<"input_data="<<input_data<<endl;
cout<<"enc_buffer="<<enc_buffer<<endl;
cout<<"dec_buffer="<<dec_buffer<<endl;
}
so, I have 3 questions
Is encrypted data always the same for same input_data and aes_key?
Is there any random key generator API?
What systemcall is there for random numbers in Linux c++?
Is encrypted data always the same for same input_data and aes_key?
No. It is the same for the same key, iv, & data.
Is there any random key generator API?
Yes, OpenSSL has one, for instance.
What systemcall is there for random numbers in Linux c++?
A "good" random number generator is /dev/urandom. Arguably better, if available, is /dev/hwrng, however it is different, not necessarily better. /dev/random is similar, possibly better to /dev/urandom but will block when sufficient entropy is not available.
In all cases you read these devices just as you would read data from a file.
enc_buffer[buffer_size+1]='\0'
Don't do that, this is a buffer overflow. The maximum index on both your buffers is [buffer_size].
memset(iv,0x00,AES_BLOCK_SIZE);
Don't do that, using the same iv (Initialization Vector) guarantees that your ciphertext will also be the same. For encryption, initialize the iv with random bits as Claris mentioned. For decryption you can ignore the iv output.

RSA Signature Size Mismatch

As stated here, the length of the message signature is equal to the modulus of the Private Key, aka the Public Key.
I'm implementing a system that signs a message, and I have a size mismatch that I can't solve.
I use crypto++.
Here is the code I use :
/* Create RSA Keys */
RSA::PrivateKey privateKey;
privateKey.GenerateRandomWithKeySize(prng, 3072);
RSA::PublicKey publicKey(privateKey);
cout << ">> RSA Keys generated";
/* Key Size */
string spki;
StringSink sSink(spki);
publicKey.Save(sSink);
cout <<" ("<< spki.size()<<" bytes)"<<endl;
RSASSA_PKCS1v15_SHA_Signer signer(privateKey);
size_t length = signer.MaxSignatureLength();
cout <<"MaxSignatureLength " <<length<<endl;
SecByteBlock signature( length );
And the output is :
>> RSA Keys generated (420 bytes)
>> ServerHello sent (436 bytes)
MaxSignatureLength 384
RSA Signature length 384
Shouldn't the MaxSignatureLength, and the RSA Signature length 420 bytes long ?
Is the problem with the algorithm I use ?
Shouldn't the MaxSignatureLength, and the RSA Signature length 420 bytes long ?
No. You are asking for a key with 3072-bits or 384 bytes. That's the limit on the size of the signature.
Each cryptosystem will likely be different in this area.
cout <<" ("<< spki.size()<<" bytes)"<<endl;
This is the size of {OID,n,e} with the ASN.1 framing or overhead. See your previous question Sending PublicKey within packet payload for what it looks like (in particular, the output of the command dumpasn1 rsa-public.der).
cout <<"MaxSignatureLength " <<length<<endl;
This is n - 1 for RSA, if I recall correctly.
Is the problem with the algorithm I use ?
No, you are doing things correctly by calling MaxSignatureLength().
>> RSA Keys generated (420 bytes)
>> ServerHello sent (436 bytes)
I'm just speculating, but it appears you appear to have design issues, too.
When you encrypt a message, like the ServerHello, you usually encrypt it under a symmetric cipher, like AES or Camellia. Then, you take that symmetric cipher key, and encrypt it under the RSA key. Finally, you send the pair {encrypted symmetric cipher key, encrypted message under symmetric cipher} to the other party.
In the system partially described above, you're only encrypting 16 or 32 bytes under the public key.
I think what you should be doing is using an Integrated Encryption Scheme to send encrypted message back and forth. For that, see Elliptic Curve Integrated Encryption Scheme (ECIES) and Discrete Logarithm Integrated Encryption Scheme (DLIES). ECIES operates over elliptic curves, and DLIES operate over integers.
Integrated Encryption Schemes have some very desireable security properties, like they are IND-CCA2. They achieve it by not allowing you to do some things, like reusing a security context, so the security is baked into the scheme.
You still have to solve the key distribution problem, though. That's a thorny problem, and we don't have a good, scalable solution.
And now you see why algorithm agility is important, and why you want that OID sent as part of the key during the handshake phase :)

MS OPM (Output Protection Manager) Initializing X509 chain

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

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).

Character encoding problem with QextSerialPort (Qt/C++)

I am developing a Qt/C++ programme in QtCreator that reads and writes from/to the serial port using QextSerialPort. My programme sends commands to a Rhino Mark IV controller and must read the response of those commands (just in case they produce any response). My development and deployment platform is Windows XP Professional.
When the Mark IV sends a response to a command and my programme reads that response from the serial port buffer, the data are not properly encoded; my programme does not seem to get plain ASCII data. For example, when the Mark IV sends an ASCII "0" (decimal 48) followed by a carriage return (decimal 13), my buffer (char *) gets -80 and 13. Characters are not properly encoded, but carriage returns are indeed. I have tried using both read (char *data, qint64 maxSize) and readAll ().
I have been monitoring the serial port traffic using two monitors that interpret ASCII data and display the corresponding characters, and the data sent in both ways seem to be correctly encoded (they are actually displayed correctly). Given that QByteArray does not interpret any character encoding and that I have tried using both read (char *data, qint64 maxSize) and readAll (), I have discarded that the problem may be caused by Qt. However, I am not sure if the problem is caused by QextSerialPort, because my programme send (writes) data properly, but does not read the correct bytes.
I have also tried talking to the Mark IV controller by hand using HyperTerminal, and the communication takes place correctly, too. I set up the connection using HyperTerminal with the following parammeters:
Baud rate: 9600
Data bits: 8
Parity bits: 0
Stop bits: 1
Flow control: Hardware
My programme sets up the serial port using the same parammeters. HyperTerminal works, my programme does not.
I started using QextSerialPort 1.1 from qextserialport.sourceforge.net and then tried with the latest source code from QextSerialPort on Google Code, and the problem remains.
What is causing the wrong character encoding?
What do I have to do to solve this issue?
48 vs. -80 smells like a signed char vs. unsigned char mismatch to me. Try with explicit unsigned char* instead of char*.
Finally, I have realized that I was not configuring the serial port correctly, as suggested by Judge Maygarden. I did not find that information in the device's manual, but in the manual of a software product developed for that device.
The correct way to set up the serial port for connecting to the Mark IV controller is to set
Baud rate: 9600
Data bits: 7
Parity: even
Stop bits: 2 bits
Flow control: Hardware
However, I am still wondering why did HyperTerminal show the characters properly even with the wrong configuration.