/src/ghostpdl/base/smd5.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2023 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* MD5Encode filter */ |
18 | | #include "memory_.h" |
19 | | #include "strimpl.h" |
20 | | #include "stream.h" |
21 | | #include "smd5.h" |
22 | | |
23 | | /* ------ MD5Encode ------ */ |
24 | | |
25 | | private_st_MD5E_state(); |
26 | | |
27 | | /* Initialize the state. */ |
28 | | static int |
29 | | s_MD5E_init(stream_state * st) |
30 | 68.0k | { |
31 | 68.0k | stream_MD5E_state *const ss = (stream_MD5E_state *) st; |
32 | | |
33 | 68.0k | gs_md5_init(&ss->md5); |
34 | 68.0k | return 0; |
35 | 68.0k | } |
36 | | |
37 | | /* Process a buffer. */ |
38 | | static int |
39 | | s_MD5E_process(stream_state * st, stream_cursor_read * pr, |
40 | | stream_cursor_write * pw, bool last) |
41 | 532k | { |
42 | 532k | stream_MD5E_state *const ss = (stream_MD5E_state *) st; |
43 | 532k | int status = 0; |
44 | | |
45 | 532k | if (pr->ptr < pr->limit) { |
46 | 464k | gs_md5_append(&ss->md5, pr->ptr + 1, pr->limit - pr->ptr); |
47 | 464k | pr->ptr = pr->limit; |
48 | 464k | } |
49 | 532k | if (last) { |
50 | 68.0k | if (pw->limit - pw->ptr >= 16) { |
51 | 34.0k | gs_md5_finish(&ss->md5, pw->ptr + 1); |
52 | 34.0k | pw->ptr += 16; |
53 | 34.0k | status = EOFC; |
54 | 34.0k | } else |
55 | 34.0k | status = 1; |
56 | 68.0k | } |
57 | 532k | return status; |
58 | 532k | } |
59 | | |
60 | | /* Stream template */ |
61 | | const stream_template s_MD5E_template = { |
62 | | &st_MD5E_state, s_MD5E_init, s_MD5E_process, 1, 16 |
63 | | }; |
64 | | |
65 | | stream * |
66 | | s_MD5E_make_stream(gs_memory_t *mem, byte *digest, int digest_size) |
67 | 34.0k | { |
68 | 34.0k | stream *s = s_alloc(mem, "s_MD5E_make_stream"); |
69 | 34.0k | stream_state *ss = s_alloc_state(mem, s_MD5E_template.stype, "s_MD5E_make_stream"); |
70 | | |
71 | 34.0k | if (ss == NULL || s == NULL) |
72 | 0 | goto err; |
73 | 34.0k | ss->templat = &s_MD5E_template; |
74 | 34.0k | if (s_init_filter(s, ss, digest, digest_size, NULL) < 0) |
75 | 0 | goto err; |
76 | 34.0k | s->strm = s; |
77 | 34.0k | return s; |
78 | 0 | err: |
79 | 0 | gs_free_object(mem, ss, "s_MD5E_make_stream"); |
80 | 0 | gs_free_object(mem, s, "s_MD5E_make_stream"); |
81 | 0 | return NULL; |
82 | 34.0k | } |
83 | | |
84 | | /* Process a buffer. */ |
85 | | static int |
86 | | s_MD5C_process(stream_state * st, stream_cursor_read * pr, |
87 | | stream_cursor_write * pw, bool last) |
88 | 29.9M | { |
89 | 29.9M | stream_MD5E_state *const ss = (stream_MD5E_state *) st; |
90 | 29.9M | int nr = pr->limit - pr->ptr; |
91 | 29.9M | int nw = pw->limit - pw->ptr; |
92 | 29.9M | int n = min(nr, nw); |
93 | | |
94 | 29.9M | gs_md5_append(&ss->md5, pr->ptr + 1, n); |
95 | 29.9M | memcpy(pw->ptr + 1, pr->ptr + 1, n); |
96 | 29.9M | pr->ptr += n; |
97 | 29.9M | pw->ptr += n; |
98 | 29.9M | if (pw->limit == pw->ptr) |
99 | 23.9M | return 1; |
100 | 6.07M | return 0; |
101 | 29.9M | } |
102 | | /* Stream template */ |
103 | | const stream_template s_MD5C_template = { |
104 | | &st_MD5E_state, s_MD5E_init, s_MD5C_process, 1, 1024 |
105 | | }; |
106 | | |
107 | | stream * |
108 | | s_MD5C_make_stream(gs_memory_t *mem, stream *strm) |
109 | 34.0k | { |
110 | 34.0k | stream *s = s_alloc(mem, "s_MD5E_make_stream"); |
111 | 34.0k | stream_state *ss = s_alloc_state(mem, s_MD5E_template.stype, "s_MD5E_make_stream"); |
112 | 34.0k | int buffer_size = 1024; |
113 | 34.0k | byte *buffer = gs_alloc_bytes(mem, buffer_size, "s_MD5E_make_stream(buffer)"); |
114 | | |
115 | 34.0k | if (ss == NULL || s == NULL || buffer == NULL) |
116 | 0 | goto err; |
117 | 34.0k | ss->templat = &s_MD5C_template; |
118 | 34.0k | if (s_init_filter(s, ss, buffer, buffer_size, NULL) < 0) |
119 | 0 | goto err; |
120 | 34.0k | s->strm = strm; |
121 | 34.0k | s->close_strm = true; |
122 | 34.0k | return s; |
123 | 0 | err: |
124 | 0 | gs_free_object(mem, ss, "s_MD5E_make_stream"); |
125 | 0 | gs_free_object(mem, s, "s_MD5E_make_stream"); |
126 | 0 | gs_free_object(mem, buffer, "s_MD5E_make_stream"); |
127 | 0 | return NULL; |
128 | 34.0k | } |
129 | | |
130 | | /* Get a digest. Apply 'flush' before calling. */ |
131 | | int |
132 | | s_MD5C_get_digest(stream *s, byte *buf, int buf_length) |
133 | 9.18k | { |
134 | 9.18k | stream_MD5E_state *const ss = (stream_MD5E_state *)s->state; |
135 | 9.18k | gs_md5_state_t md5; |
136 | 9.18k | byte b[16], *p; |
137 | 9.18k | int l = min(16, buf_length), k; |
138 | | |
139 | 9.18k | if (s->procs.process != s_MD5C_process) |
140 | 1 | return 0; /* Must not happen. */ |
141 | 9.17k | md5 = ss->md5; |
142 | 9.17k | gs_md5_finish(&md5, b); |
143 | 9.17k | memcpy(buf, b, l); |
144 | 27.5k | for (p = b + l; p < b + sizeof(b); p += l) { |
145 | 110k | for (k = 0; k < l && p + k < b + sizeof(b); k++) |
146 | 91.7k | buf[k] ^= p[k]; |
147 | 18.3k | } |
148 | 9.17k | return l; |
149 | 9.18k | } |