3GPP加密核心算法,Kasumi F8/F9解密,C代码

网友投稿 347 2022-10-14


3GPP加密核心算法,Kasumi F8/F9解密,C代码

3GPP加密核心算法,Kasumi F8/F9解密算法代码,已实战验证过正确性。

f8.c

/*------------------------------------------------------------------- *F8-Confidentiality Algorithm *------------------------------------------------------------------- * *A sample implementation of f8,the 3GPP Confidentiality algorithm. * *This has been coded for clarity,not necessarily for efficiency. * *This will compile and run correctly on both Intel(little endian) *and Sparc(big endian)machines.(Compilers used supported 32-bit ints) * *Version 1.0 05 November 1999 * *-------------------------------------------------------------------*/ #include "Common.h" #include "kasumi.h" /*--------------------------------------------------------- *f8() *Given key,count,bearer,direction,data, *and bit length encrypt the bit stream *---------------------------------------------------------*/ void f8(uint8_t*key,int count,int bearer,int dir,uint8_t*data,int length) { REGISTER64 A;/*the modifier*/ REGISTER64 temp;/*The working register*/ int i,n; uint8_t ModKey[16];/*Modified key*/ uint16_t blkcnt;/*The block counter*/ Kasumi_t sys; /*Start by building our global modifier*/ temp.b32[0]=temp.b32[1]=0; A.b32[0]=A.b32[1]=0; /*initialise register in an endian correct manner*/ A.b8[0]=(uint8_t)(count>>24); A.b8[1]=(uint8_t)(count>>16); A.b8[2]=(uint8_t)(count>>8); A.b8[3]=(uint8_t)(count); A.b8[4]=(uint8_t)(bearer<<3); A.b8[4]|=(uint8_t)(dir<<2); /*Construct the modified key and then"kasumi"A*/ for (n = 0; n < 16; ++n) { ModKey[n] = (uint8_t)(key[n] ^ 0x55); } KeySchedule(&sys, ModKey); Kasumi(&sys, A.b8);/*First encryption to create modifier*/ /*Final initialisation steps*/ blkcnt=0; KeySchedule(&sys, key); /*Now run the block cipher*/ while (length > 0) { /*First we calculate the next 64-bits of keystream*/ /*XOR in A and BLKCNT to last value*/ temp.b32[0] ^= A.b32[0]; temp.b32[1] ^= A.b32[1]; temp.b8[7] ^= (uint8_t)blkcnt; temp.b8[6] ^= (uint8_t)(blkcnt >> 8); /*KASUMI it to produce the next block of keystream*/ Kasumi(&sys, temp.b8); /*Setto the number of bytes of input data* *we have to modify.(=8 if length<=64)*/ if (length >= 64) n = 8; else n = (length + 7) / 8; /*XOR the keystream with the input data stream*/ for (i = 0; i < n; ++i) *data++ ^= temp.b8[i]; length -= 64;/*done another 64 bits*/ ++blkcnt;/*increment BLKCNT*/ } } /*----------------------------------------------------------- *e n d o f f 8.c *-----------------------------------------------------------*/

f9.c

/*------------------------------------------------------------------- *F9-Integrity Algorithm *------------------------------------------------------------------- * *A sample implementation of f9,the 3GPP Integrity algorithm. * *This has been coded for clarity,not necessarily for efficiency. * *This will compile and run correctly on both Intel(little endian) *and Sparc(big endian)machines.(Compilers used supported 32-bit ints) * *Version 1.1 05 September 2000 * *-------------------------------------------------------------------*/ #include "Common.h" #include "kasumi.h" /*--------------------------------------------------------- *f9() *Given key,count,fresh,direction,data, *and message length,calculate the hash value *---------------------------------------------------------*/ void f9(uint8_t *key,int count,int fresh,int dir,uint8_t *data,int length, uint8_t mac_i[4]) { REGISTER64 A;/*Holds the CBC chained data*/ REGISTER64 B;/*Holds the XOR of all KASUMI outputs*/ uint8_t FinalBit[8]={0x80,0x40,0x20,0x10,8,4,2,1}; uint8_t ModKey[16]; Kasumi_t sys; int i,n; /*Start by initialising the block cipher*/ KeySchedule(&sys, key); /*Next initialise the MAC chain.Make sure we* *have the data in the right byte order.* *holds our chaining value...* *is the running XOR of all KASUMI o/ps*/ for(n=0;n<4;++n) { A.b8[n]=(uint8_t)(count>>(24-(n*8))); A.b8[n+4]=(uint8_t)(fresh>>(24-(n*8))); } Kasumi(&sys, A.b8); B.b32[0]=A.b32[0]; B.b32[1]=A.b32[1]; /*Now run the blocks until we reach the last block*/ while(length>=64) { for(n=0;n<8;++n) A.b8[n]^=*data++; Kasumi(&sys, A.b8); length-=64; B.b32[0]^=A.b32[0];/*running XOR across*/ B.b32[1]^=A.b32[1];/*the block outputs*/ } /*Process whole bytes in the last block*/ n=0; while(length>=8) { A.b8[n++]^=*data++; length-=8; } /*Now add the direction bit to the input bit stream* *If length(which holds the#of data bits in the* *last byte)is non-zero we add it in,otherwise* *it has to start a new byte.*/ if(length) { i=*data; if(dir) i|=FinalBit[length]; } else i=dir?0x80:0; A.b8[n++]^=(uint8_t)i; /*Now add in the final'1'bit.The problem here* *is if the message length happens to be n*64-1.* *If so we need to process this block and then* *create a new input block of 0x8000000000000000.*/ if((length==7)&&(n==8))/*then we've filled the block*/ { Kasumi(&sys, A.b8); B.b32[0]^=A.b32[0];/*running XOR across*/ B.b32[1]^=A.b32[1];/*the block outputs*/ A.b8[0]^=0x80;/*toggle first bit*/ i=0x80; n=1; } else { if(length==7)/*we finished off the last byte*/ A.b8[n]^=0x80;/*so start a new one.....*/ else A.b8[n-1]^=FinalBit[length+1]; } Kasumi(&sys, A.b8); B.b32[0]^=A.b32[0];/*running XOR across*/ B.b32[1]^=A.b32[1];/*the block outputs*/ /*Final step is to KASUMI what we have using the* *key XORd with 0xAAAA.....*/ for(n=0;n<16;++n) ModKey[n]=(uint8_t)*key++^0xAA; KeySchedule(&sys, ModKey); Kasumi(&sys, B.b8); /*We return the left-most 32-bits of the result*/ for(n=0;n<4;++n) mac_i[n]=B.b8[n]; } /*----------------------------------------------------------- *end of f9.c *-----------------------------------------------------------*/

kasumi.h

#ifndef _KASUMI_H_INCLUDE_ #define _KASUMI_H_INCLUDE_ /*--------------------------------------------------------- *Kasumi.h *---------------------------------------------------------*/ /*-----a 64-bit structure to help with endian issues-----*/ typedef union { uint32_t b32[2]; uint16_t b16[4]; uint8_t b8[8]; }REGISTER64; /*--------globals:The subkey arrays-----------------------------------*/ typedef struct { uint16_t KLi1[8]; uint16_t KLi2[8]; uint16_t KOi1[8]; uint16_t KOi2[8]; uint16_t KOi3[8]; uint16_t KIi1[8]; uint16_t KIi2[8]; uint16_t KIi3[8]; }Kasumi_t; #ifdef __cplusplus extern "C" { #endif /*-------------prototypes--------------------------------*/ void Kasumi(Kasumi_t* p_sys, uint8_t *data); void KeySchedule(Kasumi_t* p_sys, uint8_t *k); void f9(uint8_t*key,int count,int fresh,int dir,uint8_t*data,int length, uint8_t mac_i[4]); void f8(uint8_t*key,int count,int bearer,int dir,uint8_t*data,int length); #ifdef __cplusplus } #endif #endif //_KASUMI_H_INCLUDE_

kasumi.c

/*----------------------------------------------------------------------- *Kasumi.c *----------------------------------------------------------------------- * *A sample implementation of KASUMI,the core algorithm for the *3GPP Confidentiality and Integrity algorithms. * *This has been coded for clarity,not necessarily for efficiency. * *This will compile and run correctly on both Intel(little endian) *and Sparc(big endian)machines. * *Version 1.0 14 October 1999 * *-----------------------------------------------------------------------*/ #include "Common.h" #include "Kasumi.h" /*---------16 bit rotate left------------------------------------------*/ #define ROL16(a,b) (uint16_t)((a<>(16-b))) /*-------unions:used to remove"endian"issues------------------------*/ typedef union{ uint32_t b32; uint16_t b16[2]; uint8_t b8[4]; }REGISTER32_t; typedef union{ uint16_t b16; uint8_t b8[2]; }REGISTER16_t; /*--------------------------------------------------------------------- *FI() *The FI function(fig 3).It includes the S7 and S9 tables. *Transforms a 16-bit value. *---------------------------------------------------------------------*/ static uint16_t FI(uint16_t in,uint16_t subkey) { uint16_t nine,seven; static uint16_t S7[]={ 54,50,62,56,22,34,94,96,38,6,63,93,2,18,123,33, 55,113,39,114,21,67,65,12,47,73,46,27,25,111,124,81, 53,9,121,79,52,60,58,48,101,127,40,120,104,70,71,43, 20,122,72,61,23,109,13,100,77,1,16,7,82,10,105,98, 117,116,76,11,89,106,0,125,118,99,86,69,30,57,126,87, 112,51,17,5,95,14,90,84,91,8,35,103,32,97,28,66, 102,31,26,45,75,4,85,92,37,74,80,49,68,29,115,44, 64,107,108,24,110,83,36,78,42,19,15,41,88,119,59,3}; static uint16_t S9[]={ 167,239,161,379,391,334,9,338,38,226,48,358,452,385,90,397, 183,253,147,331,415,340,51,362,306,500,262,82,216,159,356,177, 175,241,489,37,206,17,0,333,44,254,378,58,143,220,81,400, 95,3,315,245,54,235,218,405,472,264,172,494,371,290,399,76, 165,197,395,121,257,480,423,212,240,28,462,176,406,507,288,223, 501,407,249,265,89,186,221,428,164,74,440,196,458,421,350,163, 232,158,134,354,13,250,491,142,191,69,193,425,152,227,366,135, 344,300,276,242,437,320,113,278,11,243,87,317,36,93,496,27, 487,446,482,41,68,156,457,131,326,403,339,20,39,115,442,124, 475,384,508,53,112,170,479,151,126,169,73,268,279,321,168,364, 363,292,46,499,393,327,324,24,456,267,157,460,488,426,309,229, 439,506,208,271,349,401,434,236,16,209,359,52,56,120,199,277, 465,416,252,287,246,6,83,305,420,345,153,502,65,61,244,282, 173,222,418,67,386,368,261,101,476,291,195,430,49,79,166,330, 280,383,373,128,382,408,155,495,367,388,274,107,459,417,62,454, 132,225,203,316,234,14,301,91,503,286,424,211,347,307,140,374, 35,103,125,427,19,214,453,146,498,314,444,230,256,329,198,285, 50,116,78,410,10,205,510,171,231,45,139,467,29,86,505,32, 72,26,342,150,313,490,431,238,411,325,149,473,40,119,174,355, 185,233,389,71,448,273,372,55,110,178,322,12,469,392,369,190, 1,109,375,137,181,88,75,308,260,484,98,272,370,275,412,111, 336,318,4,504,492,259,304,77,337,435,21,357,303,332,483,18, 47,85,25,497,474,289,100,269,296,478,270,106,31,104,433,84, 414,486,394,96,99,154,511,148,413,361,409,255,162,215,302,201, 266,351,343,144,441,365,108,298,251,34,182,509,138,210,335,133, 311,352,328,141,396,346,123,319,450,281,429,228,443,481,92,404, 485,422,248,297,23,213,130,466,22,217,283,70,294,360,419,127, 312,377,7,468,194,2,117,295,463,258,224,447,247,187,80,398, 284,353,105,390,299,471,470,184,57,200,348,63,204,188,33,451, 97,30,310,219,94,160,129,493,64,179,263,102,189,207,114,402, 438,477,387,122,192,42,381,5,145,118,180,449,293,323,136,380, 43,66,60,455,341,445,202,432,8,237,15,376,436,464,59,461}; /*The sixteen bit input is split into two unequal halves,* *nine bits and seven bits-as is the subkey*/ nine = (uint16_t)(in >> 7); seven = (uint16_t)(in & 0x7F); /*Now run the various operations*/ nine = (uint16_t)(S9[nine] ^ seven); seven = (uint16_t)(S7[seven] ^ (nine & 0x7F)); seven ^= (subkey >> 9); nine ^= (subkey & 0x1FF); nine = (uint16_t)(S9[nine] ^ seven); seven = (uint16_t)(S7[seven] ^ (nine & 0x7F)); in = (uint16_t)((seven << 9) + nine); return(in); } /*--------------------------------------------------------------------- *FO() *The FO()function. *Transforms a 32-bit value.Usesto identify the *appropriate subkeys to use. *---------------------------------------------------------------------*/ static uint32_t FO(Kasumi_t* p_sys, uint32_t in,int index) { uint16_t left, right; /*Split the input into two 16-bit words*/ left = (uint16_t)(in >> 16); right = (uint16_t)in; /*Now apply the same basic transformation three times*/ left ^= p_sys->KOi1[index]; left = FI(left, p_sys->KIi1[index]); left ^= right; right ^= p_sys->KOi2[index]; right = FI(right, p_sys->KIi2[index]); right ^= left; left ^= p_sys->KOi3[index]; left = FI(left, p_sys->KIi3[index]); left ^= right; in = ((uint32_t)right << 16) + left; return(in); } /*--------------------------------------------------------------------- *FL() *The FL()function. *Transforms a 32-bit value.Usesto identify the *appropriate subkeys to use. *---------------------------------------------------------------------*/ static uint32_t FL(Kasumi_t* p_sys, uint32_t in,int index) { uint16_t l, r, a, b; /*split out the left and right halves*/ l = (uint16_t)(in >> 16); r = (uint16_t)(in); /*do the FL()operations*/ a = (uint16_t)(l&p_sys->KLi1[index]); r ^= ROL16(a, 1); b = (uint16_t)(r | p_sys->KLi2[index]); l ^= ROL16(b, 1); /*put the two halves back together*/ in = ((uint32_t)l << 16) + r; return(in); } /*--------------------------------------------------------------------- *Kasumi() *the Main algorithm(fig 1).Apply the same pair of operations *four times.Transforms the 64-bit input. *---------------------------------------------------------------------*/ void Kasumi(Kasumi_t* p_sys, uint8_t *data) { uint32_t left, right, temp; REGISTER32_t*d; int n; /*Start by getting the data into two 32-bit words(endian corect)*/ d = (REGISTER32_t*)data; left = ((uint32_t)d[0].b8[0] << 24) + ((uint32_t)d[0].b8[1] << 16) + ((uint32_t)d[0].b8[2] << 8) + ((uint32_t)d[0].b8[3]); right = ((uint32_t)d[1].b8[0] << 24) + ((uint32_t)d[1].b8[1] << 16) + ((uint32_t)d[1].b8[2] << 8) + ((uint32_t)d[1].b8[3]); n = 0; do { temp = FL(p_sys, left, n); temp = FO(p_sys, temp, n++); right ^= temp; temp = FO(p_sys, right, n); temp = FL(p_sys, temp, n++); left ^= temp; } while (n <= 7); /*return the correct endian result*/ d[0].b8[0] = (uint8_t)(left >> 24); d[1].b8[0] = (uint8_t)(right >> 24); d[0].b8[1] = (uint8_t)(left >> 16); d[1].b8[1] = (uint8_t)(right >> 16); d[0].b8[2] = (uint8_t)(left >> 8); d[1].b8[2] = (uint8_t)(right >> 8); d[0].b8[3] = (uint8_t)(left); d[1].b8[3] = (uint8_t)(right); } /*--------------------------------------------------------------------- *KeySchedule() *Build the key schedule.Most"key"operations use 16-bit *subkeys so we build u16-sized arrays that are"endian"correct. *---------------------------------------------------------------------*/ void KeySchedule(Kasumi_t* p_sys, uint8_t *k) { static uint16_t C[] = { 0x0123,0x4567,0x89AB,0xCDEF,0xFEDC,0xBA98,0x7654,0x3210 }; uint16_t key[8], Kprime[8]; REGISTER16_t*k16; int n; /*Start by ensuring the subkeys are endian correct on a 16-bit basis*/ k16 = (REGISTER16_t*)k; for (n = 0; n < 8; ++n) { key[n] = (((uint16_t)k16[n].b8[0] << 8) + ((uint16_t)k16[n].b8[1])); } /*Now build the K’[]keys*/ for (n = 0; n < 8; ++n) Kprime[n] = (uint16_t)(key[n] ^ C[n]); /*Finally construct the various sub keys*/ for (n = 0; n < 8; ++n) { p_sys->KLi1[n] = ROL16(key[n], 1); p_sys->KLi2[n] = Kprime[(n + 2) & 0x7]; p_sys->KOi1[n] = ROL16(key[(n + 1) & 0x7], 5); p_sys->KOi2[n] = ROL16(key[(n + 5) & 0x7], 8); p_sys->KOi3[n] = ROL16(key[(n + 6) & 0x7], 13); p_sys->KIi1[n] = Kprime[(n + 4) & 0x7]; p_sys->KIi2[n] = Kprime[(n + 3) & 0x7]; p_sys->KIi3[n] = Kprime[(n + 7) & 0x7]; } } /*--------------------------------------------------------------------- *e n d o f k a s u m i.c *---------------------------------------------------------------------*/


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:spring集成httpclient配置的详细过程
下一篇:Java JUC中操作List安全类的集合案例
相关文章

 发表评论

暂时没有评论,来抢沙发吧~