comparison libpurple/cipher.c @ 31666:3af51303d45c

Moved sha256 to the sub library
author Gary Kramlich <grim@reaperworld.com>
date Mon, 14 Feb 2011 06:20:59 +0000
parents 1bdc5f464802
children 076d62344ede
comparison
equal deleted inserted replaced
31665:1bdc5f464802 31666:3af51303d45c
921 NULL, /* get block size */ 921 NULL, /* get block size */
922 NULL /* set key with len */ 922 NULL /* set key with len */
923 }; 923 };
924 924
925 /******************************************************************************* 925 /*******************************************************************************
926 * SHA-256
927 ******************************************************************************/
928 #define SHA256_HMAC_BLOCK_SIZE 64
929
930 static size_t
931 sha256_get_block_size(PurpleCipherContext *context)
932 {
933 /* This does not change (in this case) */
934 return SHA256_HMAC_BLOCK_SIZE;
935 }
936
937 #if GLIB_CHECK_VERSION(2,16,0)
938
939 static void
940 sha256_init(PurpleCipherContext *context, void *extra)
941 {
942 purple_g_checksum_init(context, G_CHECKSUM_SHA256);
943 }
944
945 static void
946 sha256_reset(PurpleCipherContext *context, void *extra)
947 {
948 purple_g_checksum_reset(context, G_CHECKSUM_SHA256);
949 }
950
951 static gboolean
952 sha256_digest(PurpleCipherContext *context, gsize in_len, guchar digest[20],
953 gsize *out_len)
954 {
955 return purple_g_checksum_digest(context, G_CHECKSUM_SHA256, in_len,
956 digest, out_len);
957 }
958
959 static PurpleCipherOps SHA256Ops = {
960 NULL, /* Set Option */
961 NULL, /* Get Option */
962 sha256_init, /* init */
963 sha256_reset, /* reset */
964 purple_g_checksum_uninit, /* uninit */
965 NULL, /* set iv */
966 purple_g_checksum_append, /* append */
967 sha256_digest, /* digest */
968 NULL, /* encrypt */
969 NULL, /* decrypt */
970 NULL, /* set salt */
971 NULL, /* get salt size */
972 NULL, /* set key */
973 NULL, /* get key size */
974 NULL, /* set batch mode */
975 NULL, /* get batch mode */
976 sha256_get_block_size, /* get block size */
977 NULL /* set key with len */
978 };
979
980 #else /* GLIB_CHECK_VERSION(2,16,0) */
981
982 #define SHA256_ROTR(X,n) ((((X) >> (n)) | ((X) << (32-(n)))) & 0xFFFFFFFF)
983
984 static const guint32 sha256_K[64] =
985 {
986 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
987 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
988 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
989 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
990 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
991 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
992 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
993 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
994 };
995
996 struct SHA256Context {
997 guint32 H[8];
998 guint32 W[64];
999
1000 gint lenW;
1001
1002 guint32 sizeHi;
1003 guint32 sizeLo;
1004 };
1005
1006 static void
1007 sha256_hash_block(struct SHA256Context *sha256_ctx) {
1008 gint i;
1009 guint32 A, B, C, D, E, F, G, H, T1, T2;
1010
1011 for(i = 16; i < 64; i++) {
1012 sha256_ctx->W[i] =
1013 (SHA256_ROTR(sha256_ctx->W[i-2], 17) ^ SHA256_ROTR(sha256_ctx->W[i-2], 19) ^ (sha256_ctx->W[i-2] >> 10))
1014 + sha256_ctx->W[i-7]
1015 + (SHA256_ROTR(sha256_ctx->W[i-15], 7) ^ SHA256_ROTR(sha256_ctx->W[i-15], 18) ^ (sha256_ctx->W[i-15] >> 3))
1016 + sha256_ctx->W[i-16];
1017 }
1018
1019 A = sha256_ctx->H[0];
1020 B = sha256_ctx->H[1];
1021 C = sha256_ctx->H[2];
1022 D = sha256_ctx->H[3];
1023 E = sha256_ctx->H[4];
1024 F = sha256_ctx->H[5];
1025 G = sha256_ctx->H[6];
1026 H = sha256_ctx->H[7];
1027
1028 for(i = 0; i < 64; i++) {
1029 T1 = H
1030 + (SHA256_ROTR(E, 6) ^ SHA256_ROTR(E, 11) ^ SHA256_ROTR(E, 25))
1031 + ((E & F) ^ ((~E) & G))
1032 + sha256_K[i] + sha256_ctx->W[i];
1033 T2 = (SHA256_ROTR(A, 2) ^ SHA256_ROTR(A, 13) ^ SHA256_ROTR(A, 22))
1034 + ((A & B) ^ (A & C) ^ (B & C));
1035 H = G;
1036 G = F;
1037 F = E;
1038 E = D + T1;
1039 D = C;
1040 C = B;
1041 B = A;
1042 A = T1 + T2;
1043 }
1044
1045 sha256_ctx->H[0] += A;
1046 sha256_ctx->H[1] += B;
1047 sha256_ctx->H[2] += C;
1048 sha256_ctx->H[3] += D;
1049 sha256_ctx->H[4] += E;
1050 sha256_ctx->H[5] += F;
1051 sha256_ctx->H[6] += G;
1052 sha256_ctx->H[7] += H;
1053 }
1054
1055 static void
1056 sha256_set_opt(PurpleCipherContext *context, const gchar *name, void *value) {
1057 struct SHA256Context *ctx;
1058
1059 ctx = purple_cipher_context_get_data(context);
1060
1061 if(!strcmp(name, "sizeHi")) {
1062 ctx->sizeHi = GPOINTER_TO_INT(value);
1063 } else if(!strcmp(name, "sizeLo")) {
1064 ctx->sizeLo = GPOINTER_TO_INT(value);
1065 } else if(!strcmp(name, "lenW")) {
1066 ctx->lenW = GPOINTER_TO_INT(value);
1067 }
1068 }
1069
1070 static void *
1071 sha256_get_opt(PurpleCipherContext *context, const gchar *name) {
1072 struct SHA256Context *ctx;
1073
1074 ctx = purple_cipher_context_get_data(context);
1075
1076 if(!strcmp(name, "sizeHi")) {
1077 return GINT_TO_POINTER(ctx->sizeHi);
1078 } else if(!strcmp(name, "sizeLo")) {
1079 return GINT_TO_POINTER(ctx->sizeLo);
1080 } else if(!strcmp(name, "lenW")) {
1081 return GINT_TO_POINTER(ctx->lenW);
1082 }
1083
1084 return NULL;
1085 }
1086
1087 static void
1088 sha256_init(PurpleCipherContext *context, void *extra) {
1089 struct SHA256Context *sha256_ctx;
1090
1091 sha256_ctx = g_new0(struct SHA256Context, 1);
1092
1093 purple_cipher_context_set_data(context, sha256_ctx);
1094
1095 purple_cipher_context_reset(context, extra);
1096 }
1097
1098 static void
1099 sha256_reset(PurpleCipherContext *context, void *extra) {
1100 struct SHA256Context *sha256_ctx;
1101 gint i;
1102
1103 sha256_ctx = purple_cipher_context_get_data(context);
1104
1105 g_return_if_fail(sha256_ctx);
1106
1107 sha256_ctx->lenW = 0;
1108 sha256_ctx->sizeHi = 0;
1109 sha256_ctx->sizeLo = 0;
1110
1111 sha256_ctx->H[0] = 0x6a09e667;
1112 sha256_ctx->H[1] = 0xbb67ae85;
1113 sha256_ctx->H[2] = 0x3c6ef372;
1114 sha256_ctx->H[3] = 0xa54ff53a;
1115 sha256_ctx->H[4] = 0x510e527f;
1116 sha256_ctx->H[5] = 0x9b05688c;
1117 sha256_ctx->H[6] = 0x1f83d9ab;
1118 sha256_ctx->H[7] = 0x5be0cd19;
1119
1120 for(i = 0; i < 64; i++)
1121 sha256_ctx->W[i] = 0;
1122 }
1123
1124 static void
1125 sha256_uninit(PurpleCipherContext *context) {
1126 struct SHA256Context *sha256_ctx;
1127
1128 purple_cipher_context_reset(context, NULL);
1129
1130 sha256_ctx = purple_cipher_context_get_data(context);
1131
1132 memset(sha256_ctx, 0, sizeof(struct SHA256Context));
1133
1134 g_free(sha256_ctx);
1135 sha256_ctx = NULL;
1136 }
1137
1138
1139 static void
1140 sha256_append(PurpleCipherContext *context, const guchar *data, size_t len) {
1141 struct SHA256Context *sha256_ctx;
1142 gint i;
1143
1144 sha256_ctx = purple_cipher_context_get_data(context);
1145
1146 g_return_if_fail(sha256_ctx);
1147
1148 for(i = 0; i < len; i++) {
1149 sha256_ctx->W[sha256_ctx->lenW / 4] <<= 8;
1150 sha256_ctx->W[sha256_ctx->lenW / 4] |= data[i];
1151
1152 if((++sha256_ctx->lenW) % 64 == 0) {
1153 sha256_hash_block(sha256_ctx);
1154 sha256_ctx->lenW = 0;
1155 }
1156
1157 sha256_ctx->sizeLo += 8;
1158 sha256_ctx->sizeHi += (sha256_ctx->sizeLo < 8);
1159 }
1160 }
1161
1162 static gboolean
1163 sha256_digest(PurpleCipherContext *context, size_t in_len, guchar digest[32],
1164 size_t *out_len)
1165 {
1166 struct SHA256Context *sha256_ctx;
1167 guchar pad0x80 = 0x80, pad0x00 = 0x00;
1168 guchar padlen[8];
1169 gint i;
1170
1171 g_return_val_if_fail(in_len >= 32, FALSE);
1172
1173 sha256_ctx = purple_cipher_context_get_data(context);
1174
1175 g_return_val_if_fail(sha256_ctx, FALSE);
1176
1177 padlen[0] = (guchar)((sha256_ctx->sizeHi >> 24) & 255);
1178 padlen[1] = (guchar)((sha256_ctx->sizeHi >> 16) & 255);
1179 padlen[2] = (guchar)((sha256_ctx->sizeHi >> 8) & 255);
1180 padlen[3] = (guchar)((sha256_ctx->sizeHi >> 0) & 255);
1181 padlen[4] = (guchar)((sha256_ctx->sizeLo >> 24) & 255);
1182 padlen[5] = (guchar)((sha256_ctx->sizeLo >> 16) & 255);
1183 padlen[6] = (guchar)((sha256_ctx->sizeLo >> 8) & 255);
1184 padlen[7] = (guchar)((sha256_ctx->sizeLo >> 0) & 255);
1185
1186 /* pad with a 1, then zeroes, then length */
1187 purple_cipher_context_append(context, &pad0x80, 1);
1188 while(sha256_ctx->lenW != 56)
1189 purple_cipher_context_append(context, &pad0x00, 1);
1190 purple_cipher_context_append(context, padlen, 8);
1191
1192 for(i = 0; i < 32; i++) {
1193 digest[i] = (guchar)(sha256_ctx->H[i / 4] >> 24);
1194 sha256_ctx->H[i / 4] <<= 8;
1195 }
1196
1197 purple_cipher_context_reset(context, NULL);
1198
1199 if(out_len)
1200 *out_len = 32;
1201
1202 return TRUE;
1203 }
1204
1205 static PurpleCipherOps SHA256Ops = {
1206 sha256_set_opt, /* Set Option */
1207 sha256_get_opt, /* Get Option */
1208 sha256_init, /* init */
1209 sha256_reset, /* reset */
1210 sha256_uninit, /* uninit */
1211 NULL, /* set iv */
1212 sha256_append, /* append */
1213 sha256_digest, /* digest */
1214 NULL, /* encrypt */
1215 NULL, /* decrypt */
1216 NULL, /* set salt */
1217 NULL, /* get salt size */
1218 NULL, /* set key */
1219 NULL, /* get key size */
1220 NULL, /* set batch mode */
1221 NULL, /* get batch mode */
1222 sha256_get_block_size, /* get block size */
1223 NULL /* set key with len */
1224 };
1225
1226 #endif /* GLIB_CHECK_VERSION(2,16,0) */
1227 /*******************************************************************************
1228 * Structs 926 * Structs
1229 ******************************************************************************/ 927 ******************************************************************************/
1230 struct _PurpleCipher { 928 struct _PurpleCipher {
1231 gchar *name; /**< Internal name - used for searching */ 929 gchar *name; /**< Internal name - used for searching */
1232 PurpleCipherOps *ops; /**< Operations supported by this cipher */ 930 PurpleCipherOps *ops; /**< Operations supported by this cipher */
1405 static gint handle; 1103 static gint handle;
1406 1104
1407 return &handle; 1105 return &handle;
1408 } 1106 }
1409 1107
1108 /* This are implemented in the purple-ciphers sublibrary built in the ciphers
1109 * directory. We could put a header file in there, but it's less hassle for
1110 * the developer to just add it here since they have to register it here as
1111 * well.
1112 */
1410 PurpleCipherOps *purple_hmac_cipher_get_ops(); 1113 PurpleCipherOps *purple_hmac_cipher_get_ops();
1411 PurpleCipherOps *purple_md4_cipher_get_ops(); 1114 PurpleCipherOps *purple_md4_cipher_get_ops();
1412 PurpleCipherOps *purple_md5_cipher_get_ops(); 1115 PurpleCipherOps *purple_md5_cipher_get_ops();
1413 PurpleCipherOps *purple_rc4_cipher_get_ops(); 1116 PurpleCipherOps *purple_rc4_cipher_get_ops();
1414 PurpleCipherOps *purple_sha1_cipher_get_ops(); 1117 PurpleCipherOps *purple_sha1_cipher_get_ops();
1118 PurpleCipherOps *purple_sha256_cipher_get_ops();
1415 1119
1416 void 1120 void
1417 purple_ciphers_init() { 1121 purple_ciphers_init() {
1418 gpointer handle; 1122 gpointer handle;
1419 1123
1428 purple_value_new(PURPLE_TYPE_SUBTYPE, 1132 purple_value_new(PURPLE_TYPE_SUBTYPE,
1429 PURPLE_SUBTYPE_CIPHER)); 1133 PURPLE_SUBTYPE_CIPHER));
1430 1134
1431 purple_ciphers_register_cipher("md5", purple_md5_cipher_get_ops()); 1135 purple_ciphers_register_cipher("md5", purple_md5_cipher_get_ops());
1432 purple_ciphers_register_cipher("sha1", purple_sha1_cipher_get_ops()); 1136 purple_ciphers_register_cipher("sha1", purple_sha1_cipher_get_ops());
1433 purple_ciphers_register_cipher("sha256", &SHA256Ops); 1137 purple_ciphers_register_cipher("sha256", purple_sha256_cipher_get_ops());
1434 purple_ciphers_register_cipher("md4", purple_md4_cipher_get_ops()); 1138 purple_ciphers_register_cipher("md4", purple_md4_cipher_get_ops());
1435 purple_ciphers_register_cipher("hmac", purple_hmac_cipher_get_ops()); 1139 purple_ciphers_register_cipher("hmac", purple_hmac_cipher_get_ops());
1436 purple_ciphers_register_cipher("des", &DESOps); 1140 purple_ciphers_register_cipher("des", &DESOps);
1437 purple_ciphers_register_cipher("des3", &DES3Ops); 1141 purple_ciphers_register_cipher("des3", &DES3Ops);
1438 purple_ciphers_register_cipher("rc4", purple_rc4_cipher_get_ops()); 1142 purple_ciphers_register_cipher("rc4", purple_rc4_cipher_get_ops());
1452 1156
1453 g_list_free(ciphers); 1157 g_list_free(ciphers);
1454 1158
1455 purple_signals_unregister_by_instance(purple_ciphers_get_handle()); 1159 purple_signals_unregister_by_instance(purple_ciphers_get_handle());
1456 } 1160 }
1161
1457 /****************************************************************************** 1162 /******************************************************************************
1458 * PurpleCipherContext API 1163 * PurpleCipherContext API
1459 *****************************************************************************/ 1164 *****************************************************************************/
1460 void 1165 void
1461 purple_cipher_context_set_option(PurpleCipherContext *context, const gchar *name, 1166 purple_cipher_context_set_option(PurpleCipherContext *context, const gchar *name,