Mercurial > pidgin
comparison libpurple/cipher.c @ 31217: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
31216:1bdc5f464802 | 31217: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, |