在尝试使用Brian Gladman博士的AES-GCM时,为什么会出现段错误?

时间:2011-10-06 18:54:47

标签: c encryption segmentation-fault aes

我正在尝试使用Brian Gladman博士着名的AES加密程序,在这种情况下是Galois Counter Mode版本,我遇到了段错误,无法找到原因。

我写了一个小小的演示程序,它显示了我正在尝试做的事情,事实上它似乎有用,但最后它是段错误。

我在C中有点生疏,所以对于更明智的人来说错误可能是显而易见的。

这是我的程序,我希望它尽可能简短易读:

/* This program tries to be a demo for Dr Brian Gladman's AES-GCM encryption code.
   The plan is to use AES-GCM to encrypt a short message, and provide an authentication key.
   And then to decrypt the ciphertext, verifying the authentication tag on the way.*/

#include<stdio.h>
#include<assert.h>

#include "aes-modes/gcm.h"

/*note that uint_8t is Dr Gladman's type, not to be confused with uint8_t from C99*/

void print_uint_8t_array(uint_8t *a, int len, char* name)
{
  int i;
  printf("%-10s:", name);

  for(i=0; i< len; i++){
    if(a[i]==0x00) printf("-");
    else if(a[i]>=0x20 && a[i]<=0x7e) printf("%c", a[i]); 
    else printf("~");
  }
  printf("\n");
}

#define p8(name) (print_uint_8t_array((name), (sizeof(name)), (#name)))

/*Dr Gladman's functions return 0,1 or -1, to be interpreted so:*/
void interpret_retval(AES_RETURN retval){
  switch(retval){
  case      0: 
    printf("RETURN_GOOD\n");
    break;
  case 1:
    printf("RETURN_WARN\n");
    break;
  case -1:
    printf("RETURN_ERROR\n");
    break;
  default: printf("Unknown return value");
    assert(0);
    break;
  }
}

int main(void){
  printf("GCM-AES encryption/decryption/authentication example\n");

  aes_init(); 
  /*I think that this is only needed if you've compiled the libraries to make up
    their tables at runtime. If the tables are compiled in, then it's
    unnecessary but probably doesn't do any harm.*/

  uint_8t key[32]="01234567890123456789012345678901"; 
  uint_8t iv[32]="01234567890123456789012345678901";

  uint_8t header[]="Here is a header, which is not to be encrypted, but which is nevertheless to be proved to have been placed in the message by someone who knows the key.";
  uint_8t message[]="Here is some text which is to be protected from the prying eyes of those who do not know the key, whilst at the same time it is to carry along with it an unencrypted header, and a with them both a tag proving beyond reasonable doubt that the two were packaged together and run through the aes-gcm algorithm by someone who knew the key."; 
  uint_8t tag[32]="01234567890123456789012345678901";

  void printtexts(void)
  {
    printf("-----------------------------------\n");
    p8(key);
    p8(iv);
    printf("-----------------------------------\n");
    p8(header);
    p8(message);
    p8(tag);
    printf("-----------------------------------\n");
  }

  printtexts();

  {
    gcm_ctx ecx[1];
    printf("encrypting....\n");
    gcm_init_and_key(key, sizeof(key), ecx);
    interpret_retval(gcm_encrypt_message(iv, sizeof(iv), header, sizeof(header), message, sizeof(message), tag, sizeof(tag), ecx));
    gcm_end(ecx);
    printf("done\n");
  }

  printtexts();

  {
    gcm_ctx dcx[1];

    printf("decrypting....\n");
    gcm_init_and_key(key, sizeof(key), dcx);
    interpret_retval(gcm_decrypt_message(iv, sizeof(iv), header, sizeof(header), message, sizeof(message), tag, sizeof(tag), dcx));
    gcm_end(dcx);
    printf("done\n");
  }

  printtexts();

  return 0;

}

这是结果。所有加密/解密和标记似乎都有效,但是返回代码和段错误都是错误的。

jla@jaspden-desktop$ ./test3
GCM-AES encryption/decryption/authentication example
-----------------------------------
key       :01234567890123456789012345678901
iv        :01234567890123456789012345678901
-----------------------------------
header    :Here is a header, which is not to be encrypted, but which is nevertheless to be proved to have been placed in the message by someone who knows the key.-
message   :Here is some text which is to be protected from the prying eyes of those who do not know the key, whilst at the same time it is to carry along with it an unencrypted header, and a with them both a tag proving beyond reasonable doubt that the two were packaged together and run through the aes-gcm algorithm by someone who knew the key.-
tag       :01234567890123456789012345678901
-----------------------------------
encrypting....
RETURN_GOOD
done
-----------------------------------
key       :01234567890123456789012345678901
iv        :01234567890123456789012345678901
-----------------------------------
header    :Here is a header, which is not to be encrypted, but which is nevertheless to be proved to have been placed in the message by someone who knows the key.-
message   :~(}Hr~|o~~:~D~~~~3~~T~C~C(l~~~'~~~UC~D~~~~&O~ ~L~-~~~E&~~~~!~~~~~K~~~~M<|l%<ho~"~[A~0~~O~3T~%8K~~~L~~~~~~~~~7~~~~~~~~e~~~~;~392~8<~~ ~~v,E~~~~~~~~~~~W~yd~~C$H~~~*r~~~_~~~~O~u~h\9s~~`%~~~~~&~~~~~~.~~Q~~~Y~Ix~A~~~a5~~~~|~~9J~~~~~~~~ ~~ZOiX~~~~~~f~~`e~~~Ju~Z~~~X~g~OX~C~~~~~~~~~(~~gyT~~x~L~4>~Z~~ge~~~08~;~@~s~3~~WA~~~~Z-~~~~/~~~~~~Tj~bL~~
tag       :|~~,~2~~Ec~~~A~~~~~_j{~~~~`~~~u~
-----------------------------------
decrypting....
RETURN_ERROR
done
-----------------------------------
key       :01234567890123456789012345678901
iv        :01234567890123456789012345678901
-----------------------------------
header    :Here is a header, which is not to be encrypted, but which is nevertheless to be proved to have been placed in the message by someone who knows the key.-
message   :Here is some text which is to be protected from the prying eyes of those who do not know the key, whilst at the same time it is to carry along with it an unencrypted header, and a with them both a tag proving beyond reasonable doubt that the two were packaged together and run through the aes-gcm algorithm by someone who knew the key.-
tag       :|~~,~2~~Ec~~~A~~~~~_j{~~~~`~~~u~
-----------------------------------
Segmentation fault (core dumped)

1 个答案:

答案 0 :(得分:4)

自我回答,以防其他人对使用这些例程感兴趣。

显然,AES-GSM的最大标签大小为16个字节。将标签长度更改为16或更小(我在这里将其更改为32),一切正常。

此限制似乎被硬编码为gcm_decrypt_message为BLOCK_SIZE。将其更改为32似乎也有效,但只有主知道这对算法的加密属性有何影响。

在调试说明中,gcc有一个选项-fstack-protector-all,它可以在粉碎返回堆栈的过程中捕获库,这就是这里发生的事情。

据我所知,当主要尝试返回由库写入堆栈的完全虚构的地址时会导致段错误。