@@ -124,6 +124,114 @@ checksummer(struct scatterlist *sg, void *data)
124
124
return crypto_hash_update (desc , sg , sg -> length );
125
125
}
126
126
127
+ static int
128
+ arcfour_hmac_md5_usage_to_salt (unsigned int usage , u8 salt [4 ])
129
+ {
130
+ unsigned int ms_usage ;
131
+
132
+ switch (usage ) {
133
+ case KG_USAGE_SIGN :
134
+ ms_usage = 15 ;
135
+ break ;
136
+ case KG_USAGE_SEAL :
137
+ ms_usage = 13 ;
138
+ break ;
139
+ default :
140
+ return EINVAL ;;
141
+ }
142
+ salt [0 ] = (ms_usage >> 0 ) & 0xff ;
143
+ salt [1 ] = (ms_usage >> 8 ) & 0xff ;
144
+ salt [2 ] = (ms_usage >> 16 ) & 0xff ;
145
+ salt [3 ] = (ms_usage >> 24 ) & 0xff ;
146
+
147
+ return 0 ;
148
+ }
149
+
150
+ static u32
151
+ make_checksum_hmac_md5 (struct krb5_ctx * kctx , char * header , int hdrlen ,
152
+ struct xdr_buf * body , int body_offset , u8 * cksumkey ,
153
+ unsigned int usage , struct xdr_netobj * cksumout )
154
+ {
155
+ struct hash_desc desc ;
156
+ struct scatterlist sg [1 ];
157
+ int err ;
158
+ u8 checksumdata [GSS_KRB5_MAX_CKSUM_LEN ];
159
+ u8 rc4salt [4 ];
160
+ struct crypto_hash * md5 ;
161
+ struct crypto_hash * hmac_md5 ;
162
+
163
+ if (cksumkey == NULL )
164
+ return GSS_S_FAILURE ;
165
+
166
+ if (cksumout -> len < kctx -> gk5e -> cksumlength ) {
167
+ dprintk ("%s: checksum buffer length, %u, too small for %s\n" ,
168
+ __func__ , cksumout -> len , kctx -> gk5e -> name );
169
+ return GSS_S_FAILURE ;
170
+ }
171
+
172
+ if (arcfour_hmac_md5_usage_to_salt (usage , rc4salt )) {
173
+ dprintk ("%s: invalid usage value %u\n" , __func__ , usage );
174
+ return GSS_S_FAILURE ;
175
+ }
176
+
177
+ md5 = crypto_alloc_hash ("md5" , 0 , CRYPTO_ALG_ASYNC );
178
+ if (IS_ERR (md5 ))
179
+ return GSS_S_FAILURE ;
180
+
181
+ hmac_md5 = crypto_alloc_hash (kctx -> gk5e -> cksum_name , 0 ,
182
+ CRYPTO_ALG_ASYNC );
183
+ if (IS_ERR (hmac_md5 )) {
184
+ crypto_free_hash (md5 );
185
+ return GSS_S_FAILURE ;
186
+ }
187
+
188
+ desc .tfm = md5 ;
189
+ desc .flags = CRYPTO_TFM_REQ_MAY_SLEEP ;
190
+
191
+ err = crypto_hash_init (& desc );
192
+ if (err )
193
+ goto out ;
194
+ sg_init_one (sg , rc4salt , 4 );
195
+ err = crypto_hash_update (& desc , sg , 4 );
196
+ if (err )
197
+ goto out ;
198
+
199
+ sg_init_one (sg , header , hdrlen );
200
+ err = crypto_hash_update (& desc , sg , hdrlen );
201
+ if (err )
202
+ goto out ;
203
+ err = xdr_process_buf (body , body_offset , body -> len - body_offset ,
204
+ checksummer , & desc );
205
+ if (err )
206
+ goto out ;
207
+ err = crypto_hash_final (& desc , checksumdata );
208
+ if (err )
209
+ goto out ;
210
+
211
+ desc .tfm = hmac_md5 ;
212
+ desc .flags = CRYPTO_TFM_REQ_MAY_SLEEP ;
213
+
214
+ err = crypto_hash_init (& desc );
215
+ if (err )
216
+ goto out ;
217
+ err = crypto_hash_setkey (hmac_md5 , cksumkey , kctx -> gk5e -> keylength );
218
+ if (err )
219
+ goto out ;
220
+
221
+ sg_init_one (sg , checksumdata , crypto_hash_digestsize (md5 ));
222
+ err = crypto_hash_digest (& desc , sg , crypto_hash_digestsize (md5 ),
223
+ checksumdata );
224
+ if (err )
225
+ goto out ;
226
+
227
+ memcpy (cksumout -> data , checksumdata , kctx -> gk5e -> cksumlength );
228
+ cksumout -> len = kctx -> gk5e -> cksumlength ;
229
+ out :
230
+ crypto_free_hash (md5 );
231
+ crypto_free_hash (hmac_md5 );
232
+ return err ? GSS_S_FAILURE : 0 ;
233
+ }
234
+
127
235
/*
128
236
* checksum the plaintext data and hdrlen bytes of the token header
129
237
* The checksum is performed over the first 8 bytes of the
@@ -140,6 +248,11 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
140
248
u8 checksumdata [GSS_KRB5_MAX_CKSUM_LEN ];
141
249
unsigned int checksumlen ;
142
250
251
+ if (kctx -> gk5e -> ctype == CKSUMTYPE_HMAC_MD5_ARCFOUR )
252
+ return make_checksum_hmac_md5 (kctx , header , hdrlen ,
253
+ body , body_offset ,
254
+ cksumkey , usage , cksumout );
255
+
143
256
if (cksumout -> len < kctx -> gk5e -> cksumlength ) {
144
257
dprintk ("%s: checksum buffer length, %u, too small for %s\n" ,
145
258
__func__ , cksumout -> len , kctx -> gk5e -> name );
@@ -733,3 +846,145 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf,
733
846
ret = GSS_S_FAILURE ;
734
847
return ret ;
735
848
}
849
+
850
+ /*
851
+ * Compute Kseq given the initial session key and the checksum.
852
+ * Set the key of the given cipher.
853
+ */
854
+ int
855
+ krb5_rc4_setup_seq_key (struct krb5_ctx * kctx , struct crypto_blkcipher * cipher ,
856
+ unsigned char * cksum )
857
+ {
858
+ struct crypto_hash * hmac ;
859
+ struct hash_desc desc ;
860
+ struct scatterlist sg [1 ];
861
+ u8 Kseq [GSS_KRB5_MAX_KEYLEN ];
862
+ u32 zeroconstant = 0 ;
863
+ int err ;
864
+
865
+ dprintk ("%s: entered\n" , __func__ );
866
+
867
+ hmac = crypto_alloc_hash (kctx -> gk5e -> cksum_name , 0 , CRYPTO_ALG_ASYNC );
868
+ if (IS_ERR (hmac )) {
869
+ dprintk ("%s: error %ld, allocating hash '%s'\n" ,
870
+ __func__ , PTR_ERR (hmac ), kctx -> gk5e -> cksum_name );
871
+ return PTR_ERR (hmac );
872
+ }
873
+
874
+ desc .tfm = hmac ;
875
+ desc .flags = 0 ;
876
+
877
+ err = crypto_hash_init (& desc );
878
+ if (err )
879
+ goto out_err ;
880
+
881
+ /* Compute intermediate Kseq from session key */
882
+ err = crypto_hash_setkey (hmac , kctx -> Ksess , kctx -> gk5e -> keylength );
883
+ if (err )
884
+ goto out_err ;
885
+
886
+ sg_init_table (sg , 1 );
887
+ sg_set_buf (sg , & zeroconstant , 4 );
888
+
889
+ err = crypto_hash_digest (& desc , sg , 4 , Kseq );
890
+ if (err )
891
+ goto out_err ;
892
+
893
+ /* Compute final Kseq from the checksum and intermediate Kseq */
894
+ err = crypto_hash_setkey (hmac , Kseq , kctx -> gk5e -> keylength );
895
+ if (err )
896
+ goto out_err ;
897
+
898
+ sg_set_buf (sg , cksum , 8 );
899
+
900
+ err = crypto_hash_digest (& desc , sg , 8 , Kseq );
901
+ if (err )
902
+ goto out_err ;
903
+
904
+ err = crypto_blkcipher_setkey (cipher , Kseq , kctx -> gk5e -> keylength );
905
+ if (err )
906
+ goto out_err ;
907
+
908
+ err = 0 ;
909
+
910
+ out_err :
911
+ crypto_free_hash (hmac );
912
+ dprintk ("%s: returning %d\n" , __func__ , err );
913
+ return err ;
914
+ }
915
+
916
+ /*
917
+ * Compute Kcrypt given the initial session key and the plaintext seqnum.
918
+ * Set the key of cipher kctx->enc.
919
+ */
920
+ int
921
+ krb5_rc4_setup_enc_key (struct krb5_ctx * kctx , struct crypto_blkcipher * cipher ,
922
+ s32 seqnum )
923
+ {
924
+ struct crypto_hash * hmac ;
925
+ struct hash_desc desc ;
926
+ struct scatterlist sg [1 ];
927
+ u8 Kcrypt [GSS_KRB5_MAX_KEYLEN ];
928
+ u8 zeroconstant [4 ] = {0 };
929
+ u8 seqnumarray [4 ];
930
+ int err , i ;
931
+
932
+ dprintk ("%s: entered, seqnum %u\n" , __func__ , seqnum );
933
+
934
+ hmac = crypto_alloc_hash (kctx -> gk5e -> cksum_name , 0 , CRYPTO_ALG_ASYNC );
935
+ if (IS_ERR (hmac )) {
936
+ dprintk ("%s: error %ld, allocating hash '%s'\n" ,
937
+ __func__ , PTR_ERR (hmac ), kctx -> gk5e -> cksum_name );
938
+ return PTR_ERR (hmac );
939
+ }
940
+
941
+ desc .tfm = hmac ;
942
+ desc .flags = 0 ;
943
+
944
+ err = crypto_hash_init (& desc );
945
+ if (err )
946
+ goto out_err ;
947
+
948
+ /* Compute intermediate Kcrypt from session key */
949
+ for (i = 0 ; i < kctx -> gk5e -> keylength ; i ++ )
950
+ Kcrypt [i ] = kctx -> Ksess [i ] ^ 0xf0 ;
951
+
952
+ err = crypto_hash_setkey (hmac , Kcrypt , kctx -> gk5e -> keylength );
953
+ if (err )
954
+ goto out_err ;
955
+
956
+ sg_init_table (sg , 1 );
957
+ sg_set_buf (sg , zeroconstant , 4 );
958
+
959
+ err = crypto_hash_digest (& desc , sg , 4 , Kcrypt );
960
+ if (err )
961
+ goto out_err ;
962
+
963
+ /* Compute final Kcrypt from the seqnum and intermediate Kcrypt */
964
+ err = crypto_hash_setkey (hmac , Kcrypt , kctx -> gk5e -> keylength );
965
+ if (err )
966
+ goto out_err ;
967
+
968
+ seqnumarray [0 ] = (unsigned char ) ((seqnum >> 24 ) & 0xff );
969
+ seqnumarray [1 ] = (unsigned char ) ((seqnum >> 16 ) & 0xff );
970
+ seqnumarray [2 ] = (unsigned char ) ((seqnum >> 8 ) & 0xff );
971
+ seqnumarray [3 ] = (unsigned char ) ((seqnum >> 0 ) & 0xff );
972
+
973
+ sg_set_buf (sg , seqnumarray , 4 );
974
+
975
+ err = crypto_hash_digest (& desc , sg , 4 , Kcrypt );
976
+ if (err )
977
+ goto out_err ;
978
+
979
+ err = crypto_blkcipher_setkey (cipher , Kcrypt , kctx -> gk5e -> keylength );
980
+ if (err )
981
+ goto out_err ;
982
+
983
+ err = 0 ;
984
+
985
+ out_err :
986
+ crypto_free_hash (hmac );
987
+ dprintk ("%s: returning %d\n" , __func__ , err );
988
+ return err ;
989
+ }
990
+
0 commit comments