Sfoglia il codice sorgente

Adding missing gcm files for client

Sajin Sasy 1 anno fa
parent
commit
7397846e61
2 ha cambiato i file con 189 aggiunte e 0 eliminazioni
  1. 168 0
      Client/gcm.cpp
  2. 21 0
      Client/gcm.h

+ 168 - 0
Client/gcm.cpp

@@ -0,0 +1,168 @@
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include "gcm.h"
+
+/* Sample openssl GCM code lightly adapted from
+https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption
+*/
+int gcm_encrypt(unsigned char *plaintext, int plaintext_len,
+                unsigned char *aad, int aad_len,
+                unsigned char *key,
+                unsigned char *iv, int iv_len,
+                unsigned char *ciphertext,
+                unsigned char *tag)
+{
+    EVP_CIPHER_CTX *ctx;
+
+    int len;
+
+    int ciphertext_len;
+
+
+    /* Create and initialise the context */
+    if(!(ctx = EVP_CIPHER_CTX_new())) {
+        printf("EVP_CIPHER_CTX_new failed\n");
+        return -1;
+    }
+
+    /* Initialise the encryption operation. */
+    if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL)) {
+        printf("EVP_EncryptInit_ex failed\n");
+        return -1;
+    }
+
+    /*
+     * Set IV length if default 12 bytes (96 bits) is not appropriate
+     */
+    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL)) {
+        printf("EVP_CTRL_GCM_SET_IVLEN failed\n");
+        return -1;
+    }
+
+    /* Initialise key and IV */
+    if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) {
+        printf("Setting key and iv failed\n");
+        return -1;
+    }
+
+    /*
+     * Provide any AAD data. This can be called zero or more times as
+     * required
+     */
+    if(aad_len && 1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len)) {
+        printf("EVP_EncryptUpdate AAD failed\n");
+        return -1;
+    }
+
+    /*
+     * Provide the message to be encrypted, and obtain the encrypted output.
+     * EVP_EncryptUpdate can be called multiple times if necessary
+     */
+    int ret = EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len);
+    if(1 != ret) {
+        printf("EVP_EncryptUpdate failed\n");
+        return -1;
+    }
+    ciphertext_len = len;
+
+    /*
+     * Finalise the encryption. Normally ciphertext bytes may be written at
+     * this stage, but this does not occur in GCM mode
+     */
+    if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) {
+        printf("EVP_EncryptFinal_ex failed\n");
+        return -1;
+    }
+    ciphertext_len += len;
+
+    /* Get the tag */
+    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag)) {
+        printf("EVP_CTRL_GCM_GET_TAG failed\n");
+        return -1;
+    }
+
+    /* Clean up */
+    EVP_CIPHER_CTX_free(ctx);
+
+    return ciphertext_len;
+}
+
+int gcm_decrypt(unsigned char *ciphertext, int ciphertext_len,
+                unsigned char *aad, int aad_len,
+                unsigned char *tag,
+                unsigned char *key,
+                unsigned char *iv, int iv_len,
+                unsigned char *plaintext)
+{
+    EVP_CIPHER_CTX *ctx;
+    int len;
+    int plaintext_len;
+    int ret;
+
+    /* Create and initialise the context */
+    if(!(ctx = EVP_CIPHER_CTX_new())) {
+        printf("EVP_CIPHER_CTX_new failed\n");
+        return -1;
+    }
+
+    /* Initialise the decryption operation. */
+    if(!EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL)) {
+        printf("EVP_DecryptInit_ex failed\n");
+        return -1;
+    }
+
+    /* Set IV length. Not necessary if this is 12 bytes (96 bits) */
+    if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL)) {
+        printf("EVP_CTRL_GCM_SET_IVLEN failed\n");
+        return -1;
+    }
+
+    /* Initialise key and IV */
+    if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) {
+        printf("Setting key and iv failed\n");
+        return -1;
+    }
+
+    /*
+     * Provide any AAD data. This can be called zero or more times as
+     * required
+     */
+    if(aad_len && !EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len)) {
+        printf("EVP_DecryptUpdate AAD failed\n");
+        return -1;
+    }
+
+    /*
+     * Provide the message to be decrypted, and obtain the plaintext output.
+     * EVP_DecryptUpdate can be called multiple times if necessary
+     */
+    if(!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) {
+        printf("EVP_DecryptUpdate failed\n");
+        return -1;
+    }
+    plaintext_len = len;
+
+    /* Set expected tag value. Works in OpenSSL 1.0.1d and later */
+    if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag)) {
+        printf("EVP_CTRL_GCM_SET_TAG failed\n");
+        return -1;
+    }
+
+    /*
+     * Finalise the decryption. A positive return value indicates success,
+     * anything else is a failure - the plaintext is not trustworthy.
+     */
+    ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
+
+    /* Clean up */
+    EVP_CIPHER_CTX_free(ctx);
+
+    if(ret > 0) {
+        /* Success */
+        plaintext_len += len;
+        return plaintext_len;
+    } else {
+        /* Verify failed */
+        return -1;
+    }
+}

+ 21 - 0
Client/gcm.h

@@ -0,0 +1,21 @@
+#ifndef __GCM_H__
+#define __GCM_H__
+
+/* Sample openssl GCM code from
+https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption
+*/
+int gcm_encrypt(unsigned char *plaintext, int plaintext_len,
+                unsigned char *aad, int aad_len,
+                unsigned char *key,
+                unsigned char *iv, int iv_len,
+                unsigned char *ciphertext,
+                unsigned char *tag);
+
+int gcm_decrypt(unsigned char *ciphertext, int ciphertext_len,
+                unsigned char *aad, int aad_len,
+                unsigned char *tag,
+                unsigned char *key,
+                unsigned char *iv, int iv_len,
+                unsigned char *plaintext);
+
+#endif