xorriso  1.5.4.pl02
About: GNU xorriso creates, loads, manipulates and writes ISO 9660 filesystem images with Rock Ridge extensions. It is suitable for incremental data backup and for production of bootable ISO 9660 images. GNU xorriso is a statical compilation of the libraries libburn, libisofs, libisoburn, and libjte.
  Fossies Dox: xorriso-1.5.4.pl02.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

md5.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009 - 2013 Thomas Schmitt
3  *
4  * This file is part of the libisofs project; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License version 2
6  * or later as published by the Free Software Foundation.
7  * See COPYING file for details.
8  */
9 
10 
11 #ifdef HAVE_CONFIG_H
12 #include "../config.h"
13 #endif
14 
15 #ifdef HAVE_STDINT_H
16 #include <stdint.h>
17 #else
18 #ifdef HAVE_INTTYPES_H
19 #include <inttypes.h>
20 #endif
21 #endif
22 
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdio.h>
26 
27 #include "writer.h"
28 #include "messages.h"
29 #include "ecma119.h"
30 #include "image.h"
31 #include "util.h"
32 
33 #include "md5.h"
34 
35 
36 /* This code is derived from RFC 1321 and implements computation of the
37  "RSA Data Security, Inc. MD5 Message-Digest Algorithm" */
38 
39 #define Libisofs_md5_S11 7
40 #define Libisofs_md5_S12 12
41 #define Libisofs_md5_S13 17
42 #define Libisofs_md5_S14 22
43 #define Libisofs_md5_S21 5
44 #define Libisofs_md5_S22 9
45 #define Libisofs_md5_S23 14
46 #define Libisofs_md5_S24 20
47 #define Libisofs_md5_S31 4
48 #define Libisofs_md5_S32 11
49 #define Libisofs_md5_S33 16
50 #define Libisofs_md5_S34 23
51 #define Libisofs_md5_S41 6
52 #define Libisofs_md5_S42 10
53 #define Libisofs_md5_S43 15
54 #define Libisofs_md5_S44 21
55 
56 
57 /* F, G, H and I are basic MD5 functions.
58  */
59 #define Libisofs_md5_F(x, y, z) (((x) & (y)) | ((~x) & (z)))
60 #define Libisofs_md5_G(x, y, z) (((x) & (z)) | ((y) & (~z)))
61 #define Libisofs_md5_H(x, y, z) ((x) ^ (y) ^ (z))
62 #define Libisofs_md5_I(x, y, z) ((y) ^ ((x) | (~z)))
63 
64 /* ROTATE_LEFT rotates x left n bits.
65  */
66 #define Libisofs_md5_ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
67 
68 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
69 Rotation is separate from addition to prevent recomputation.
70  */
71 #define Libisofs_md5_FF(a, b, c, d, x, s, ac) { \
72  (a) += Libisofs_md5_F ((b), (c), (d)) + (x) + (uint32_t)(ac); \
73  (a) = Libisofs_md5_ROTATE_LEFT ((a), (s)); \
74  (a) += (b); \
75  }
76 #define Libisofs_md5_GG(a, b, c, d, x, s, ac) { \
77  (a) += Libisofs_md5_G ((b), (c), (d)) + (x) + (uint32_t)(ac); \
78  (a) = Libisofs_md5_ROTATE_LEFT ((a), (s)); \
79  (a) += (b); \
80  }
81 #define Libisofs_md5_HH(a, b, c, d, x, s, ac) { \
82  (a) += Libisofs_md5_H ((b), (c), (d)) + (x) + (uint32_t)(ac); \
83  (a) = Libisofs_md5_ROTATE_LEFT ((a), (s)); \
84  (a) += (b); \
85  }
86 #define Libisofs_md5_II(a, b, c, d, x, s, ac) { \
87  (a) += Libisofs_md5_I ((b), (c), (d)) + (x) + (uint32_t)(ac); \
88  (a) = Libisofs_md5_ROTATE_LEFT ((a), (s)); \
89  (a) += (b); \
90  }
91 
92 
93 /* MD5 context. */
95  uint32_t state[4]; /* state (ABCD) */
96  uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
97  unsigned char buffer[64]; /* input buffer */
98 };
99 
100 typedef struct _libisofs_md5_ctx libisofs_md5_ctx;
101 
102 
103 /* MD5 basic transformation. Transforms state based on block.
104  */
105 static int md5__transform (uint32_t state[4], unsigned char block[64])
106 {
107  uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
108  unsigned int i, j;
109 
110  for (i = 0, j = 0; j < 64; i++, j += 4)
111  x[i] = ((uint32_t)block[j]) | (((uint32_t)block[j+1]) << 8) |
112  (((uint32_t)block[j+2]) << 16) | (((uint32_t)block[j+3]) << 24);
113 
114  /* Round 1 */
115  Libisofs_md5_FF (a, b, c, d, x[ 0], Libisofs_md5_S11, 0xd76aa478); /* 1 */
116  Libisofs_md5_FF (d, a, b, c, x[ 1], Libisofs_md5_S12, 0xe8c7b756); /* 2 */
117  Libisofs_md5_FF (c, d, a, b, x[ 2], Libisofs_md5_S13, 0x242070db); /* 3 */
118  Libisofs_md5_FF (b, c, d, a, x[ 3], Libisofs_md5_S14, 0xc1bdceee); /* 4 */
119  Libisofs_md5_FF (a, b, c, d, x[ 4], Libisofs_md5_S11, 0xf57c0faf); /* 5 */
120  Libisofs_md5_FF (d, a, b, c, x[ 5], Libisofs_md5_S12, 0x4787c62a); /* 6 */
121  Libisofs_md5_FF (c, d, a, b, x[ 6], Libisofs_md5_S13, 0xa8304613); /* 7 */
122  Libisofs_md5_FF (b, c, d, a, x[ 7], Libisofs_md5_S14, 0xfd469501); /* 8 */
123  Libisofs_md5_FF (a, b, c, d, x[ 8], Libisofs_md5_S11, 0x698098d8); /* 9 */
124  Libisofs_md5_FF (d, a, b, c, x[ 9], Libisofs_md5_S12, 0x8b44f7af); /* 10 */
125  Libisofs_md5_FF (c, d, a, b, x[10], Libisofs_md5_S13, 0xffff5bb1); /* 11 */
126  Libisofs_md5_FF (b, c, d, a, x[11], Libisofs_md5_S14, 0x895cd7be); /* 12 */
127  Libisofs_md5_FF (a, b, c, d, x[12], Libisofs_md5_S11, 0x6b901122); /* 13 */
128  Libisofs_md5_FF (d, a, b, c, x[13], Libisofs_md5_S12, 0xfd987193); /* 14 */
129  Libisofs_md5_FF (c, d, a, b, x[14], Libisofs_md5_S13, 0xa679438e); /* 15 */
130  Libisofs_md5_FF (b, c, d, a, x[15], Libisofs_md5_S14, 0x49b40821); /* 16 */
131 
132  /* Round 2 */
133  Libisofs_md5_GG (a, b, c, d, x[ 1], Libisofs_md5_S21, 0xf61e2562); /* 17 */
134  Libisofs_md5_GG (d, a, b, c, x[ 6], Libisofs_md5_S22, 0xc040b340); /* 18 */
135  Libisofs_md5_GG (c, d, a, b, x[11], Libisofs_md5_S23, 0x265e5a51); /* 19 */
136  Libisofs_md5_GG (b, c, d, a, x[ 0], Libisofs_md5_S24, 0xe9b6c7aa); /* 20 */
137  Libisofs_md5_GG (a, b, c, d, x[ 5], Libisofs_md5_S21, 0xd62f105d); /* 21 */
138  Libisofs_md5_GG (d, a, b, c, x[10], Libisofs_md5_S22, 0x2441453); /* 22 */
139  Libisofs_md5_GG (c, d, a, b, x[15], Libisofs_md5_S23, 0xd8a1e681); /* 23 */
140  Libisofs_md5_GG (b, c, d, a, x[ 4], Libisofs_md5_S24, 0xe7d3fbc8); /* 24 */
141  Libisofs_md5_GG (a, b, c, d, x[ 9], Libisofs_md5_S21, 0x21e1cde6); /* 25 */
142  Libisofs_md5_GG (d, a, b, c, x[14], Libisofs_md5_S22, 0xc33707d6); /* 26 */
143  Libisofs_md5_GG (c, d, a, b, x[ 3], Libisofs_md5_S23, 0xf4d50d87); /* 27 */
144  Libisofs_md5_GG (b, c, d, a, x[ 8], Libisofs_md5_S24, 0x455a14ed); /* 28 */
145  Libisofs_md5_GG (a, b, c, d, x[13], Libisofs_md5_S21, 0xa9e3e905); /* 29 */
146  Libisofs_md5_GG (d, a, b, c, x[ 2], Libisofs_md5_S22, 0xfcefa3f8); /* 30 */
147  Libisofs_md5_GG (c, d, a, b, x[ 7], Libisofs_md5_S23, 0x676f02d9); /* 31 */
148  Libisofs_md5_GG (b, c, d, a, x[12], Libisofs_md5_S24, 0x8d2a4c8a); /* 32 */
149 
150  /* Round 3 */
151  Libisofs_md5_HH (a, b, c, d, x[ 5], Libisofs_md5_S31, 0xfffa3942); /* 33 */
152  Libisofs_md5_HH (d, a, b, c, x[ 8], Libisofs_md5_S32, 0x8771f681); /* 34 */
153  Libisofs_md5_HH (c, d, a, b, x[11], Libisofs_md5_S33, 0x6d9d6122); /* 35 */
154  Libisofs_md5_HH (b, c, d, a, x[14], Libisofs_md5_S34, 0xfde5380c); /* 36 */
155  Libisofs_md5_HH (a, b, c, d, x[ 1], Libisofs_md5_S31, 0xa4beea44); /* 37 */
156  Libisofs_md5_HH (d, a, b, c, x[ 4], Libisofs_md5_S32, 0x4bdecfa9); /* 38 */
157  Libisofs_md5_HH (c, d, a, b, x[ 7], Libisofs_md5_S33, 0xf6bb4b60); /* 39 */
158  Libisofs_md5_HH (b, c, d, a, x[10], Libisofs_md5_S34, 0xbebfbc70); /* 40 */
159  Libisofs_md5_HH (a, b, c, d, x[13], Libisofs_md5_S31, 0x289b7ec6); /* 41 */
160  Libisofs_md5_HH (d, a, b, c, x[ 0], Libisofs_md5_S32, 0xeaa127fa); /* 42 */
161  Libisofs_md5_HH (c, d, a, b, x[ 3], Libisofs_md5_S33, 0xd4ef3085); /* 43 */
162  Libisofs_md5_HH (b, c, d, a, x[ 6], Libisofs_md5_S34, 0x4881d05); /* 44 */
163  Libisofs_md5_HH (a, b, c, d, x[ 9], Libisofs_md5_S31, 0xd9d4d039); /* 45 */
164  Libisofs_md5_HH (d, a, b, c, x[12], Libisofs_md5_S32, 0xe6db99e5); /* 46 */
165  Libisofs_md5_HH (c, d, a, b, x[15], Libisofs_md5_S33, 0x1fa27cf8); /* 47 */
166  Libisofs_md5_HH (b, c, d, a, x[ 2], Libisofs_md5_S34, 0xc4ac5665); /* 48 */
167 
168  /* Round 4 */
169  Libisofs_md5_II (a, b, c, d, x[ 0], Libisofs_md5_S41, 0xf4292244); /* 49 */
170  Libisofs_md5_II (d, a, b, c, x[ 7], Libisofs_md5_S42, 0x432aff97); /* 50 */
171  Libisofs_md5_II (c, d, a, b, x[14], Libisofs_md5_S43, 0xab9423a7); /* 51 */
172  Libisofs_md5_II (b, c, d, a, x[ 5], Libisofs_md5_S44, 0xfc93a039); /* 52 */
173  Libisofs_md5_II (a, b, c, d, x[12], Libisofs_md5_S41, 0x655b59c3); /* 53 */
174  Libisofs_md5_II (d, a, b, c, x[ 3], Libisofs_md5_S42, 0x8f0ccc92); /* 54 */
175  Libisofs_md5_II (c, d, a, b, x[10], Libisofs_md5_S43, 0xffeff47d); /* 55 */
176  Libisofs_md5_II (b, c, d, a, x[ 1], Libisofs_md5_S44, 0x85845dd1); /* 56 */
177  Libisofs_md5_II (a, b, c, d, x[ 8], Libisofs_md5_S41, 0x6fa87e4f); /* 57 */
178  Libisofs_md5_II (d, a, b, c, x[15], Libisofs_md5_S42, 0xfe2ce6e0); /* 58 */
179  Libisofs_md5_II (c, d, a, b, x[ 6], Libisofs_md5_S43, 0xa3014314); /* 59 */
180  Libisofs_md5_II (b, c, d, a, x[13], Libisofs_md5_S44, 0x4e0811a1); /* 60 */
181  Libisofs_md5_II (a, b, c, d, x[ 4], Libisofs_md5_S41, 0xf7537e82); /* 61 */
182  Libisofs_md5_II (d, a, b, c, x[11], Libisofs_md5_S42, 0xbd3af235); /* 62 */
183  Libisofs_md5_II (c, d, a, b, x[ 2], Libisofs_md5_S43, 0x2ad7d2bb); /* 63 */
184  Libisofs_md5_II (b, c, d, a, x[ 9], Libisofs_md5_S44, 0xeb86d391); /* 64 */
185 
186  state[0] += a;
187  state[1] += b;
188  state[2] += c;
189  state[3] += d;
190 
191  /* Zeroize sensitive information. */
192  memset ((char *) x, 0, sizeof (x));
193  return(1);
194 }
195 
196 
197 static int md5__encode(unsigned char *output, uint32_t *input,
198  unsigned int len)
199 {
200  unsigned int i, j;
201 
202  for (i = 0, j = 0; j < len; i++, j += 4) {
203  output[j] = (unsigned char)(input[i] & 0xff);
204  output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
205  output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
206  output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
207  }
208  return(1);
209 }
210 
211 
212 
213 static int md5_init(libisofs_md5_ctx *ctx, int flag)
214 {
215  ctx->count[0] = ctx->count[1] = 0;
216  /* Load magic initialization constants. */
217  ctx->state[0] = 0x67452301;
218  ctx->state[1] = 0xefcdab89;
219  ctx->state[2] = 0x98badcfe;
220  ctx->state[3] = 0x10325476;
221  return(1);
222 }
223 
224 
225 /* MD5 block update operation. Continues an MD5 message-digest
226  operation, processing another message block, and updating the
227  context.
228  */
229 static int md5_update(libisofs_md5_ctx *ctx, unsigned char *data,
230  int datalen, int flag)
231 {
232  int i, index, partlen;
233 
234  /* Compute number of bytes mod 64 */
235  index = ((ctx->count[0] >> 3) & 0x3F);
236  /* Update number of bits */
237  if ((ctx->count[0] += ((uint32_t) datalen << 3)) <
238  ((uint32_t) datalen << 3))
239  ctx->count[1]++;
240  ctx->count[1] += ((uint32_t) datalen >> 29);
241  partlen = 64 - index;
242 
243  /* Transform as many times as possible. */
244  if (datalen >= partlen) {
245  memcpy((char *) &ctx->buffer[index], (char *) data, partlen);
246  md5__transform(ctx->state, ctx->buffer);
247  for (i = partlen; i + 63 < datalen; i += 64)
248  md5__transform(ctx->state, &data[i]);
249  index = 0;
250  } else
251  i = 0;
252 
253  /* Buffer remaining data */
254  memcpy((char *) &ctx->buffer[index], (char *) &data[i],datalen-i);
255 
256  return(1);
257 }
258 
259 
260 static int md5_final(libisofs_md5_ctx *ctx, char result[16], int flag)
261 {
262  unsigned char bits[8], *respt;
263  unsigned int index, padlen;
264  static unsigned char PADDING[64] = {
265  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
266  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
267  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
268  };
269 
270  /* Save number of bits */
271  md5__encode(bits, ctx->count, 8);
272  /* Pad out to 56 mod 64. */
273  index = (unsigned int)((ctx->count[0] >> 3) & 0x3f);
274  padlen = (index < 56) ? (56 - index) : (120 - index);
275  md5_update(ctx, PADDING, padlen,0);
276  /* Append length (before padding) */
277  md5_update(ctx, bits, 8,0);
278  /* Store state in result */
279  respt= (unsigned char *) result;
280  md5__encode(respt, ctx->state, 16);
281  /* Zeroize sensitive information. */
282  memset ((char *) ctx, 0, sizeof (*ctx));
283  return(1);
284 }
285 
286 /** Compute a MD5 checksum from one or more calls of this function.
287  The first call has to be made with flag bit0 == 1. It may already submit
288  processing payload in data and datalen.
289  The last call has to be made with bit15 set. Normally bit1 will be set
290  too in order to receive the checksum before it gets disposed.
291  bit1 may only be set in the last call or together with bit2.
292  The combination of bit1 and bit2 may be used to get an intermediate
293  result without hampering an ongoing checksum computation.
294 
295  @param ctx the checksum context which stores the state between calls.
296  It gets created with flag bit0 and disposed with bit15.
297  With flag bit0, *ctx has to be NULL or point to freeable
298  memory.
299  @param data the bytes to be checksummed
300  @param datalen the number of bytes in data
301  @param result returns the 16 bytes of checksum if called with bit1 set
302  @param flag bit0= allocate and init *ctx
303  bit1= transfer ctx to result
304  bit2= with bit 0 : clone new *ctx from data
305  bit15= free *ctx
306 */
307 static
308 int libisofs_md5(void **ctx_in, char *data, int datalen,
309  char result[16], int flag)
310 /* *ctx has to be NULL or point to freeable memory */
311 /*
312  bit0= allocate and init *ctx
313  bit1= transfer ctx to result
314  bit2= with bit 0 : clone new *ctx from data
315  bit15= free *ctx
316 */
317 {
318  unsigned char *datapt;
319  libisofs_md5_ctx **ctx;
320 
321  ctx= (libisofs_md5_ctx **) ctx_in;
322  if(flag&1) {
323  if(*ctx!=NULL)
324  free((char *) *ctx);
325  *ctx= calloc(1, sizeof(libisofs_md5_ctx));
326  if(*ctx==NULL)
327  return(-1);
328  md5_init(*ctx,0);
329  if(flag&4)
330  memcpy((char *) *ctx,data,sizeof(libisofs_md5_ctx));
331  }
332  if(*ctx==NULL)
333  return(0);
334  if(datalen>0) {
335  datapt= (unsigned char *) data;
336  md5_update(*ctx, datapt, datalen, 0);
337  }
338  if(flag&2)
339  md5_final(*ctx, result, 0);
340  if(flag&(1<<15)) {
341  free((char *) *ctx);
342  *ctx= NULL;
343  }
344  return(1);
345 }
346 
347 
348 /* ----------------------------------------------------------------------- */
349 
350 /* Public MD5 computing facility */
351 
352 /* API */
353 int iso_md5_start(void **md5_context)
354 {
355  int ret;
356 
357  ret = libisofs_md5(md5_context, NULL, 0, NULL, 1);
358  if (ret <= 0)
359  return ISO_OUT_OF_MEM;
360  return 1;
361 }
362 
363 
364 /* API */
365 int iso_md5_compute(void *md5_context, char *data, int datalen)
366 {
367  int ret;
368 
369  ret = libisofs_md5(&md5_context, data, datalen, NULL, 0);
370  if (ret <= 0)
371  return ISO_NULL_POINTER;
372  return 1;
373 }
374 
375 
376 /* API */
377 int iso_md5_clone(void *old_md5_context, void **new_md5_context)
378 {
379  int ret;
380 
381  ret = libisofs_md5(new_md5_context, old_md5_context, 0, NULL, 1 | 4);
382  if (ret < 0)
383  return ISO_OUT_OF_MEM;
384  if (ret == 0)
385  return ISO_NULL_POINTER;
386  return 1;
387 }
388 
389 
390 /* API */
391 int iso_md5_end(void **md5_context, char result[16])
392 {
393  int ret;
394 
395  ret = libisofs_md5(md5_context, NULL, 0, result, 2 | (1 << 15));
396  if (ret <= 0)
397  return ISO_NULL_POINTER;
398  return 1;
399 }
400 
401 
402 /* API */
403 int iso_md5_match(char first_md5[16], char second_md5[16])
404 {
405  int i;
406 
407  for (i= 0; i < 16; i++)
408  if (first_md5[i] != second_md5[i])
409  return 0;
410  return 1;
411 }
412 
413 
414 /* ----------------------------------------------------------------------- */
415 
416 
417 /* Function to identify and manage md5sum indice of the old image.
418  * data is supposed to be a 4 byte integer, bit 31 shall be 0,
419  * value 0 of this integer means that it is not a valid index.
420  */
421 int checksum_cx_xinfo_func(void *data, int flag)
422 {
423  /* data is an int disguised as pointer. It does not point to memory. */
424  return 1;
425 }
426 
427 /* The iso_node_xinfo_cloner function which gets associated to
428  * checksum_cx_xinfo_func by iso_init() resp. iso_init_with_flag() via
429  * iso_node_xinfo_make_clonable()
430  */
431 int checksum_cx_xinfo_cloner(void *old_data, void **new_data, int flag)
432 {
433  *new_data = NULL;
434  if (flag)
435  return ISO_XINFO_NO_CLONE;
436  if (old_data == NULL)
437  return 0;
438  /* data is an int disguised as pointer. It does not point to memory. */
439  *new_data = old_data;
440  return 0;
441 }
442 
443 
444 /* Function to identify and manage md5 sums of unspecified providence stored
445  * directly in this xinfo.
446  */
447 int checksum_md5_xinfo_func(void *data, int flag)
448 {
449  if (data == NULL)
450  return 1;
451  free(data);
452  return 1;
453 }
454 
455 /* The iso_node_xinfo_cloner function which gets associated to
456  * checksum_md5_xinfo_func by iso_init() resp. iso_init_with_flag() via
457  * iso_node_xinfo_make_clonable()
458  */
459 int checksum_md5_xinfo_cloner(void *old_data, void **new_data, int flag)
460 {
461  *new_data = NULL;
462  if (flag)
463  return ISO_XINFO_NO_CLONE;
464  if (old_data == NULL)
465  return 0;
466  *new_data = calloc(1, 16);
467  if (*new_data == NULL)
468  return ISO_OUT_OF_MEM;
469  memcpy(*new_data, old_data, 16);
470  return 16;
471 }
472 
473 
474 /* ----------------------------------------------------------------------- */
475 
476 /* MD5 checksum image writer */
477 
478 /*
479  @flag bit0= recursion
480  bit1= session will be appended to an existing image
481 */
482 static
483 int checksum_copy_old_nodes(Ecma119Image *target, IsoNode *node, int flag)
484 {
485  IsoNode *pos;
486  IsoFile *file;
487  IsoImage *img;
488  int ret, i;
489  size_t value_length;
490  unsigned int idx = 0, old_idx = 0;
491  char *value = NULL, *md5_pt = NULL;
492  void *xipt;
493 
494  img = target->image;
495  if (target->checksum_buffer == NULL)
496  return 0;
497 
498  if (node->type == LIBISO_FILE) {
499  file = (IsoFile *) node;
500  if (file->from_old_session && target->opts->appendable) {
501  /* Look for checksums at various places */
502 
503  /* Try checksum directly stored with node */
504  if (md5_pt == NULL) {
505  ret = iso_node_get_xinfo(node, checksum_md5_xinfo_func, &xipt);
506  if (ret < 0)
507  return ret;
508  if (ret == 1)
509  md5_pt = (char *) xipt;
510  }
511 
512  /* Try checksum index to image checksum buffer */
513  if (md5_pt == NULL && img->checksum_array != NULL) {
514  ret = iso_node_get_xinfo(node, checksum_cx_xinfo_func, &xipt);
515  if (ret <= 0)
516  return ret;
517  /* xipt is an int disguised as void pointer */
518  old_idx = 0;
519  for (i = 0; i < 4; i++)
520  old_idx = (old_idx << 8) | ((unsigned char *) &xipt)[i];
521 
522  if (old_idx == 0 || old_idx > img->checksum_idx_count - 1)
523  return 0;
524  md5_pt = img->checksum_array + 16 * old_idx;
525  }
526 
527  if (md5_pt == NULL)
528  return 0;
529 
530  if (!target->opts->will_cancel) {
531  ret = iso_node_lookup_attr(node, "isofs.cx", &value_length,
532  &value, 0);
533  if (ret == 1 && value_length == 4) {
534  for (i = 0; i < 4; i++)
535  idx = (idx << 8) | ((unsigned char *) value)[i];
536  if (idx > 0 && idx <= target->checksum_idx_counter) {
537  memcpy(target->checksum_buffer + 16 * idx, md5_pt, 16);
538  }
539  }
540  if (value != NULL)
541  free(value);
542 
543  /* >>> ts B30114 : It is unclear why these are removed here.
544  At least with the opts->will_cancel runs,
545  this is not appropriate.
546  */
548  }
549  }
550  } else if (node->type == LIBISO_DIR) {
551  for (pos = ((IsoDir *) node)->children; pos != NULL; pos = pos->next) {
552  ret = checksum_copy_old_nodes(target, pos, 1);
553  if (ret < 0)
554  return ret;
555  }
556  }
557  return ISO_SUCCESS;
558 }
559 
560 
561 static
563 {
564  size_t size;
565  Ecma119Image *t;
566  int ret;
567 
568  if (writer == NULL) {
569  return ISO_ASSERT_FAILURE;
570  }
571  t = writer->target;
572 
574  /* (t->curblock already contains t->opts->ms_block) */
576  size = (t->checksum_idx_counter + 2) / 128;
577  if (size * 128 < t->checksum_idx_counter + 2)
578  size++;
579  t->curblock += size;
582 
583  /* Extra block for stream detectable checksum tag */
584  t->checksum_tag_pos = t->curblock;
585  t->curblock++;
586 
587  /* Allocate array of MD5 sums */
588  t->checksum_buffer = calloc(size, 2048);
589  if (t->checksum_buffer == NULL)
590  return ISO_OUT_OF_MEM;
591 
592  /* Copy MD5 from nodes of old image into writer->data */
593  ret = checksum_copy_old_nodes(t, (IsoNode *) t->image->root, 0);
594  if (ret < 0)
595  return ret;
596 
597  /* Record lba,count,size,cecksum_type in "isofs.ca" of root node */
598  ret = iso_root_set_isofsca((IsoNode *) t->image->root,
601  t->checksum_idx_counter + 2, 16, "MD5", 0);
602  if (ret < 0)
603  return ret;
604  return ISO_SUCCESS;
605 }
606 
607 
608 static
610 {
611 
612  /* The superblock checksum tag has to be written after
613  the Volume Descriptor Set Terminator and thus may not be
614  written by this function. (It would have been neat, though).
615  */
616 
617  return ISO_SUCCESS;
618 }
619 
620 
621 static
623 {
624  int wres, res;
625  size_t i, size;
626  Ecma119Image *t;
627  void *ctx = NULL;
628  char md5[16];
629 
630  if (writer == NULL) {
631  return ISO_ASSERT_FAILURE;
632  }
633 
634  t = writer->target;
635  iso_msg_debug(t->image->id, "Writing Checksums...");
636 
637  /* Write image checksum to index 0 */
638  if (t->checksum_ctx != NULL) {
639  res = iso_md5_clone(t->checksum_ctx, &ctx);
640  if (res > 0) {
641  res = iso_md5_end(&ctx, t->image_md5);
642  if (res > 0)
643  memcpy(t->checksum_buffer + 0 * 16, t->image_md5, 16);
644  }
645  }
646 
647  size = (t->checksum_idx_counter + 2) / 128;
648  if (size * 128 < t->checksum_idx_counter + 2)
649  size++;
650 
651  /* Write checksum of checksum array as index t->checksum_idx_counter + 1 */
652  res = iso_md5_start(&ctx);
653  if (res > 0) {
654  for (i = 0; i < t->checksum_idx_counter + 1; i++)
655  iso_md5_compute(ctx,
656  t->checksum_buffer + ((size_t) i) * (size_t) 16, 16);
657  res = iso_md5_end(&ctx, md5);
658  if (res > 0)
659  memcpy(t->checksum_buffer + (t->checksum_idx_counter + 1) * 16,
660  md5, 16);
661  }
662 
663  for (i = 0; i < size; i++) {
664  wres = iso_write(t, t->checksum_buffer + ((size_t) 2048) * i, 2048);
665  if (wres < 0) {
666  res = wres;
667  goto ex;
668  }
669  }
670  if (t->checksum_ctx == NULL) {
671  res = ISO_SUCCESS;
672  goto ex;
673  }
674 
675  /* Write stream detectable checksum tag to extra block */;
676  res = iso_md5_write_tag(t, 1);
677  if (res < 0)
678  goto ex;
679 
680  res = ISO_SUCCESS;
681 ex:;
682  if (ctx != NULL)
683  iso_md5_end(&ctx, md5);
684  return(res);
685 }
686 
687 
688 static
690 {
691  /* nothing was allocated at writer->data */
692  return ISO_SUCCESS;
693 }
694 
695 
697 {
698  IsoImageWriter *writer;
699 
700  writer = malloc(sizeof(IsoImageWriter));
701  if (writer == NULL) {
702  return ISO_OUT_OF_MEM;
703  }
704 
709  writer->data = NULL;
710  writer->target = target;
711 
712  /* add this writer to image */
713  target->writers[target->nwriters++] = writer;
714  /* Account for superblock checksum tag */
715  if (target->opts->md5_session_checksum) {
716  target->checksum_sb_tag_pos = target->curblock;
717  target->curblock++;
718  }
719  return ISO_SUCCESS;
720 }
721 
722 
723 static
724 int iso_md5_write_scdbackup_tag(Ecma119Image *t, char *tag_block, int flag)
725 {
726  void *ctx = NULL;
727  off_t pos = 0, line_start;
728  int record_len, block_len, ret, i;
729  char postext[40], md5[16], *record = NULL;
730 
731  LIBISO_ALLOC_MEM(record, char, 160);
732  line_start = strlen(tag_block);
733  iso_md5_compute(t->checksum_ctx, tag_block, line_start);
734  ret = iso_md5_clone(t->checksum_ctx, &ctx);
735  if (ret < 0)
736  goto ex;
737  ret = iso_md5_end(&ctx, md5);
738 
739  pos = (off_t) t->checksum_tag_pos * (off_t) 2048 + line_start;
740  if(pos >= 1000000000)
741  sprintf(postext, "%u%9.9u", (unsigned int) (pos / 1000000000),
742  (unsigned int) (pos % 1000000000));
743  else
744  sprintf(postext, "%u", (unsigned int) pos);
745  sprintf(record, "%s %s ", t->opts->scdbackup_tag_parm, postext);
746  record_len = strlen(record);
747  for (i = 0; i < 16; i++)
748  sprintf(record + record_len + 2 * i,
749  "%2.2x", ((unsigned char *) md5)[i]);
750  record_len += 32;
751 
752  ret = iso_md5_start(&ctx);
753  if (ret < 0)
754  goto ex;
755  iso_md5_compute(ctx, record, record_len);
756  iso_md5_end(&ctx, md5);
757 
758  sprintf(tag_block + line_start, "scdbackup_checksum_tag_v0.1 %s %d %s ",
759  postext, record_len, record);
760  block_len = strlen(tag_block);
761  for (i = 0; i < 16; i++)
762  sprintf(tag_block + block_len + 2 * i,
763  "%2.2x", ((unsigned char *) md5)[i]);
764  block_len+= 32;
765  tag_block[block_len++]= '\n';
766 
767  if (t->opts->scdbackup_tag_written != NULL)
768  strncpy(t->opts->scdbackup_tag_written, tag_block + line_start,
769  block_len - line_start);
770  ret = ISO_SUCCESS;
771 ex:;
772  if (ctx != NULL)
773  iso_md5_end(&ctx, md5);
774  LIBISO_FREE_MEM(record);
775  return ret;
776 }
777 
778 
779 /* Write stream detectable checksum tag to extra block.
780  * @flag bit0-7= tag type
781  * 1= session tag (End checksumming.)
782  * 2= superblock tag (System Area and Volume Descriptors)
783  * 3= tree tag (ECMA-119 and Rock Ridge tree)
784  * 4= relocated superblock tag (at LBA 0 of overwritable media)
785  * Write to target->opts_overwrite rather than to iso_write().
786  */
788 {
789  int ret, mode, l, i, wres, tag_id_len;
790  void *ctx = NULL;
791  char md5[16], *tag_block = NULL, *tag_id;
792  uint32_t size = 0, pos = 0, start;
793 
794  LIBISO_ALLOC_MEM(tag_block, char, 2048);
795  start = t->checksum_range_start;
796  mode = flag & 255;
797  if (mode < 1 || mode > 4)
798  {ret = ISO_WRONG_ARG_VALUE; goto ex;}
799  ret = iso_md5_clone(t->checksum_ctx, &ctx);
800  if (ret < 0)
801  goto ex;
802  ret = iso_md5_end(&ctx, md5);
803  if (mode == 1) {
804  size = t->checksum_range_size;
805  pos = t->checksum_tag_pos;
806  } else {
807  if (mode == 2) {
808  pos = t->checksum_sb_tag_pos;
809  } else if (mode == 3) {
810  pos = t->checksum_tree_tag_pos;
811  } else if (mode == 4) {
812  pos = t->checksum_rlsb_tag_pos;
813  start = pos - (pos % 32);
814  }
815  size = pos - start;
816  }
817  if (ret < 0)
818  goto ex;
819 
820  iso_util_tag_magic(mode, &tag_id, &tag_id_len, 0);
821  sprintf(tag_block, "%s pos=%u range_start=%u range_size=%u",
822  tag_id, pos, start, size);
823 
824  l = strlen(tag_block);
825  if (mode == 2) {
826  sprintf(tag_block + l, " next=%u", t->checksum_tree_tag_pos);
827  } else if (mode == 3) {
828  sprintf(tag_block + l, " next=%u", t->checksum_tag_pos);
829  } else if (mode == 4) {
830  sprintf(tag_block + l, " session_start=%u", t->opts->ms_block);
831  }
832  strcat(tag_block + l, " md5=");
833  l = strlen(tag_block);
834  for (i = 0; i < 16; i++)
835  sprintf(tag_block + l + 2 * i, "%2.2x",
836  ((unsigned char *) md5)[i]);
837  l+= 32;
838 
839  ret = iso_md5_start(&ctx);
840  if (ret > 0) {
841  iso_md5_compute(ctx, tag_block, l);
842  iso_md5_end(&ctx, md5);
843  strcpy(tag_block + l, " self=");
844  l += 6;
845  for (i = 0; i < 16; i++)
846  sprintf(tag_block + l + 2 * i, "%2.2x",
847  ((unsigned char *) md5)[i]);
848  }
849  tag_block[l + 32] = '\n';
850 
851  if (mode == 1 && t->opts->scdbackup_tag_parm[0]) {
852  if (t->opts->ms_block > 0) {
854  } else {
855  ret = iso_md5_write_scdbackup_tag(t, tag_block, 0);
856  if (ret < 0)
857  goto ex;
858  }
859  }
860 
861  if (mode == 4) {
862  if (t->opts_overwrite != NULL)
863  memcpy(t->opts_overwrite + pos * 2048, tag_block, 2048);
864  } else {
865  wres = iso_write(t, tag_block, 2048);
866  if (wres < 0) {
867  ret = wres;
868  goto ex;
869  }
870  }
871 
872  ret = ISO_SUCCESS;
873 ex:;
874  if (ctx != NULL)
875  iso_md5_end(&ctx, md5);
876  LIBISO_FREE_MEM(tag_block);
877  return ret;
878 }
879 
880 
int iso_write(Ecma119Image *target, void *buf, size_t count)
Definition: ecma119.c:3471
static int checksum_writer_compute_data_blocks(IsoImageWriter *writer)
Definition: md5.c:562
#define Libisofs_md5_S41
Definition: md5.c:51
int iso_md5_clone(void *old_md5_context, void **new_md5_context)
Definition: md5.c:377
int iso_md5_end(void **md5_context, char result[16])
Definition: md5.c:391
static int md5__transform(uint32_t state[4], unsigned char block[64])
Definition: md5.c:105
static int checksum_writer_free_data(IsoImageWriter *writer)
Definition: md5.c:689
#define Libisofs_md5_S23
Definition: md5.c:45
#define Libisofs_md5_S22
Definition: md5.c:44
int iso_md5_write_tag(Ecma119Image *t, int flag)
Definition: md5.c:787
#define Libisofs_md5_S34
Definition: md5.c:50
int checksum_md5_xinfo_cloner(void *old_data, void **new_data, int flag)
Definition: md5.c:459
static int md5__encode(unsigned char *output, uint32_t *input, unsigned int len)
Definition: md5.c:197
int checksum_writer_create(Ecma119Image *target)
Definition: md5.c:696
int checksum_cx_xinfo_func(void *data, int flag)
Definition: md5.c:421
#define Libisofs_md5_II(a, b, c, d, x, s, ac)
Definition: md5.c:86
int checksum_cx_xinfo_cloner(void *old_data, void **new_data, int flag)
Definition: md5.c:431
#define Libisofs_md5_S31
Definition: md5.c:47
int checksum_md5_xinfo_func(void *data, int flag)
Definition: md5.c:447
static int libisofs_md5(void **ctx_in, char *data, int datalen, char result[16], int flag)
Definition: md5.c:308
static int iso_md5_write_scdbackup_tag(Ecma119Image *t, char *tag_block, int flag)
Definition: md5.c:724
#define Libisofs_md5_S12
Definition: md5.c:40
static int checksum_copy_old_nodes(Ecma119Image *target, IsoNode *node, int flag)
Definition: md5.c:483
#define Libisofs_md5_S44
Definition: md5.c:54
static int md5_init(libisofs_md5_ctx *ctx, int flag)
Definition: md5.c:213
#define Libisofs_md5_S33
Definition: md5.c:49
int iso_md5_match(char first_md5[16], char second_md5[16])
Definition: md5.c:403
#define Libisofs_md5_HH(a, b, c, d, x, s, ac)
Definition: md5.c:81
#define Libisofs_md5_S11
Definition: md5.c:39
static int md5_update(libisofs_md5_ctx *ctx, unsigned char *data, int datalen, int flag)
Definition: md5.c:229
#define Libisofs_md5_S14
Definition: md5.c:42
static int checksum_writer_write_vol_desc(IsoImageWriter *writer)
Definition: md5.c:609
int iso_md5_start(void **md5_context)
Definition: md5.c:353
#define Libisofs_md5_GG(a, b, c, d, x, s, ac)
Definition: md5.c:76
#define Libisofs_md5_S32
Definition: md5.c:48
#define Libisofs_md5_S13
Definition: md5.c:41
int iso_md5_compute(void *md5_context, char *data, int datalen)
Definition: md5.c:365
#define Libisofs_md5_FF(a, b, c, d, x, s, ac)
Definition: md5.c:71
#define Libisofs_md5_S42
Definition: md5.c:52
static int checksum_writer_write_data(IsoImageWriter *writer)
Definition: md5.c:622
#define Libisofs_md5_S24
Definition: md5.c:46
static int md5_final(libisofs_md5_ctx *ctx, char result[16], int flag)
Definition: md5.c:260
#define Libisofs_md5_S21
Definition: md5.c:43
#define Libisofs_md5_S43
Definition: md5.c:53
int iso_util_tag_magic(int tag_type, char **tag_magic, int *len, int flag)
Definition: util.c:2130
#define LIBISO_FREE_MEM(pt)
Definition: util.h:627
#define LIBISO_ALLOC_MEM(pt, typ, count)
Definition: util.h:615
int iso_node_lookup_attr(IsoNode *node, char *name, size_t *value_length, char **value, int flag)
Definition: node.c:1757
#define ISO_SUCCESS
Definition: libisofs.h:8719
@ LIBISO_DIR
Definition: libisofs.h:229
@ LIBISO_FILE
Definition: libisofs.h:230
int iso_node_remove_xinfo(IsoNode *node, iso_node_xinfo_func proc)
Definition: node.c:172
#define ISO_OUT_OF_MEM
Definition: libisofs.h:8745
int iso_node_get_xinfo(IsoNode *node, iso_node_xinfo_func proc, void **data)
Definition: node.c:213
#define ISO_SCDBACKUP_TAG_NOT_0
Definition: libisofs.h:9028
#define ISO_XINFO_NO_CLONE
Definition: libisofs.h:9093
#define ISO_WRONG_ARG_VALUE
Definition: libisofs.h:8751
#define ISO_NULL_POINTER
Definition: libisofs.h:8742
#define ISO_ASSERT_FAILURE
Definition: libisofs.h:8737
int iso_msg_submit(int imgid, int errcode, int causedby, const char *fmt,...)
Definition: messages.c:579
void iso_msg_debug(int imgid, const char *fmt,...)
Definition: messages.c:253
int iso_root_set_isofsca(IsoNode *node, uint32_t start_lba, uint32_t end_lba, uint32_t count, uint32_t size, char *typetext, int flag)
Definition: node.c:2910
Definition: node.h:140
Definition: node.h:149
unsigned int from_old_session
Definition: node.h:155
Ecma119Image * target
Definition: writer.h:28
int(* write_data)(IsoImageWriter *writer)
Definition: writer.h:23
void * data
Definition: writer.h:27
int(* compute_data_blocks)(IsoImageWriter *writer)
Definition: writer.h:19
int(* write_vol_desc)(IsoImageWriter *writer)
Definition: writer.h:21
int(* free_data)(IsoImageWriter *writer)
Definition: writer.h:25
char * checksum_array
Definition: image.h:229
int id
Definition: image.h:97
uint32_t checksum_idx_count
Definition: image.h:228
IsoDir * root
Definition: image.h:43
Definition: node.h:100
enum IsoNodeType type
Definition: node.h:111
IsoNode * next
Definition: node.h:131
unsigned char buffer[64]
Definition: md5.c:97
uint32_t state[4]
Definition: md5.c:95
uint32_t count[2]
Definition: md5.c:96
char * opts_overwrite
Definition: ecma119.h:773
IsoImage * image
Definition: ecma119.h:560
uint32_t checksum_tag_pos
Definition: ecma119.h:766
IsoWriteOpts * opts
Definition: ecma119.h:563
uint32_t checksum_tree_tag_pos
Definition: ecma119.h:765
uint32_t checksum_rlsb_tag_pos
Definition: ecma119.h:763
uint32_t checksum_range_start
Definition: ecma119.h:770
uint32_t checksum_sb_tag_pos
Definition: ecma119.h:764
IsoImageWriter ** writers
Definition: ecma119.h:753
void * checksum_ctx
Definition: ecma119.h:761
unsigned int checksum_idx_counter
Definition: ecma119.h:760
char * checksum_buffer
Definition: ecma119.h:768
size_t nwriters
Definition: ecma119.h:752
uint32_t curblock
Definition: ecma119.h:618
uint32_t checksum_array_pos
Definition: ecma119.h:769
uint32_t checksum_range_size
Definition: ecma119.h:771
char image_md5[16]
Definition: ecma119.h:767
unsigned int md5_session_checksum
Definition: ecma119.h:270
uint32_t ms_block
Definition: ecma119.h:379
int will_cancel
Definition: ecma119.h:101
char * scdbackup_tag_written
Definition: ecma119.h:428
unsigned int appendable
Definition: ecma119.h:364
char scdbackup_tag_parm[100]
Definition: ecma119.h:422