-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathtimestamp-implementation-advice.xml
More file actions
612 lines (578 loc) · 30.8 KB
/
timestamp-implementation-advice.xml
File metadata and controls
612 lines (578 loc) · 30.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
<?xml version="1.0" encoding="US-ASCII"?> <!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
<!ENTITY RFC2119 SYSTEM
"http://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml"> <!ENTITY
RFC5280 SYSTEM
"http://xml.resource.org/public/rfc/bibxml/reference.RFC.5280.xml"> <!ENTITY
RFC5905 SYSTEM
"http://xml.resource.org/public/rfc/bibxml/reference.RFC.5905.xml"> <!ENTITY
RFC7384 SYSTEM
"http://xml.resource.org/public/rfc/bibxml/reference.RFC.7384.xml"> ]>
<?xml-stylesheet type='text/xsl' href='rfc2629.xslt' ?>
<?rfc strict="yes"?>
<?rfc toc="no"?>
<?rfc tocdepth="3"?>
<?rfc symrefs="yes"?>
<?rfc sortrefs="yes"?>
<?rfc compact="yes"?>
<?rfc subcompact="no"?>
<rfc category="info" docName="draft-aanchal-time-implementation-guidance-02" ipr="trust200902">
<front>
<title>On Implementing Time</title>
<author fullname="Aanchal Malhotra" initials="A." surname="Malhotra">
<organization>Boston University</organization>
<address>
<postal>
<street>111 Cummington Mall</street>
<city>Boston</city>
<region></region>
<code>02215</code>
<country>USA</country>
</postal>
<email>aanchal4@bu.edu</email>
</address>
</author>
<author fullname="Kristof Teichel" initials="K." surname="Teichel">
<organization abbrev="PTB">Physikalisch-Technische Bundesanstalt</organization>
<address>
<postal>
<street>Bundesallee 100</street>
<city>Braunschweig</city>
<region></region>
<code>D-38116</code>
<country>Germany</country>
</postal>
<email>kristof.teichel@ptb.de</email>
</address>
</author>
<author fullname="Martin Hoffmann" initials="M." surname="Hoffmann">
<organization>NLnet Labs</organization>
<address>
<postal>
<street>Science Park 400</street>
<city>Amsterdam</city>
<region></region>
<code>1098 XH</code>
<country>Netherlands</country>
</postal>
<email>martin@nlnetlabs.nl</email>
</address>
</author>
<author fullname="Willem Toorop" initials="W." surname="Toorop">
<organization>NLnet Labs</organization>
<address>
<postal>
<street>Science Park 400</street>
<city>Amsterdam</city>
<region></region>
<code>1098 XH</code>
<country>Netherlands</country>
</postal>
<email>willem@nlnetlabs.nl</email>
</address>
</author>
<date year="2017" month="July" day="8"/>
<area>General</area>
<workgroup>Internet Engineering Task Force</workgroup>
<keyword>timestamps</keyword>
<keyword>timespans</keyword>
<abstract>
<t>
This document describes the properties of different types of clocks
available on digital systems. It provides implementors of
applications with guidance on choices they have to make when working
with time to provide basic functionality and security guarantees.
</t>
</abstract>
</front>
<middle>
<section title="Introduction">
<t>
It is hard to understate the importance of time in modern digital systems.
The functionality and security of applications (distributed or local to one system) and that of network protocols generally hinge on some notion of time.
For implementation, these applications and protocols have to choose one of the types of clocks available on their system, each of which has its own specific properties.
However, currently many of these applications seem to be oblivious to the implications of choosing one or the other clock for implementation.
This behavior can be attributed to:
a) the lack of clear understanding of the distinct properties of these clocks,
b) trade-offs of using one or the other for an application, and
c) availability and compatibility of these clocks on different systems.
This document discusses a) and b).
</t>
<t>
More specifically, in this document we first define different methods used by protocols and applications to express time.
We then define properties of clocks maintained by modern digital systems.
Next we describe how systems obtain these values from these clocks and the security considerations of using these values to implement protocols and applications that use time.
Finally we discuss trade-offs between security and precision of choosing a clock.
The document aims to provide guidance to the implementors make an informed choice with an example of POSIX system.
</t>
</section>
<section title = "Scope of the document">
<t>
This document aims to provide software developers implementing protocols and
applications that have to deal with time with the knowledge and
understanding to make informed decisions regarding the available
clocks and their respective trade-offs.
</t>
<t>
It does not describe functionality that is specific to the
architecture of a PC, or other devices such as phones, IoT devices,
switches, routers, base stations, or synchrophasors. Nor is the
document applicable to a specific operating system.
Throughout the document we assume that one or the other clock is available on most devices.
How these clocks are available on different PCs or other devices is out of scope of this document.
</t>
<t>
We do not exactly recommend which clock should be used.
We discuss the available options and trade-offs.
The final decision would vary depending on the availability of clocks and the security requirements of the specific application under implementation.
</t>
<t>
Note: Since there is a lack of standards on terminology related to time, we define some terms in the following section.
Also, throughout the document, we define the terms as they become relevant.
Different systems, depending on their OS, may use different terms for the same types of clocks.
A survey on this is not in the scope of this document.
We provide a discussion on how to access these values on POSIX and Windows systems.
On other systems, implementors will have to determine themselves which of these values are available.
</t>
</section>
<!--
<section title = "Definitions">
<t><list style = "symbols">
<t>
Time, Timescale: Time is an abstraction which determines the ordering of events in a given frame of reference called timescale.
</t>
<t>
Oscillator: An oscillator is a device that outputs trigger signals, which are (to a given tolerance level) equidistant with respect to a timescale.
</t>
<t>
(Physical) Clock, Counter: A (physical) clock is a device composed of an oscillator and a counter, where the counter records a number of cycles since its initialization, with increments triggered by the oscillator.
</t>
</list></t>
</section>
-->
<section title = "Expressing Time">
<t>
Protocols and applications can express time in several forms,
depending on whether they need to express a point in time or
a time interval.
</t>
<section title="Absolute Time">
<t>
Absolute time expresses a universally agreed upon reference to a
specific point in time. Such a reference can be expressed in
different ways. For instance, Unix Time refers to the number of
seconds since midnight UTC, January 1st, 1970, while in everyday
life, we referenced such a point through year, month, day, and
so on.
</t>
<t>
Because absolute time expresses a shared view of time, a system
needs to synchronize its clock with a common reference clock,
for instance one base on UTC.
</t>
<t>
Absolute time is often used to express the start or end of the
validity of objects with a limited lifetime that are shared over
the network.
</t>
</section>
<section title="Relative Time">
<t>
Relative time measures the time interval that has elapsed from
some well-defined reference point (e.g., 20 minutes from the
time of your query).
</t>
<t>
Relative time is commonly used in network protocols, for instance
to determine when a packet should be considered dropped or to
express Time To Live (TTL) values that govern the length of time
for which an object is valid or usable.
</t>
<t>
Since relative time does not express a point in time, it does not
rely on synchronized clocks between systems but only on a shared
rate of passage of his time.
</t>
</section>
</section>
<section title = "Keeping Time: Different Clocks">
<t>
Because time is relative to an observer, there cannot be a
universally agreed upon time. At best we can achieve an
approximation by constantly updating our own clocks against
a shared reference clock. Remaining close to this reference
clock is a complex process with its own set of difficulties.
</t>
<t>
In this section, we will have a look at the different clocks
a system uses and how it maintains these clocks.
</t>
<section title="Native Clock">
<t>
Each system has its own perception of time. It gains access
it via its native clock. Typcially, this clock counts cycles
of an oscillator but some systems use process CPU times or
thread CPU timers (via timers provided by the CPU).
The quality of the native clock therefore dependends on either
the stability of the oscillator or the CPU timer.
</t>
<t>
The timescale of the native clock is a purely subjective -- no
general meaning can be attached to any specific clock value. One
can only obtain relative time by comparing two values. Because
the value of the native clock always grows at a steady pace,
never decreases, never make unexpected jumps, and never skips,
the difference between two clock values provides the time
intervall between the two measurements.
</t>
<t>
The independence of the native clock from any external time
sources renders it resistant to any manipulation but in return
there is no guarantee that its clock rate is similar to that
of any other system. This difference in rate, especially when
compared to a reference clock, is called clock drift.
</t>
<t>
Clock drift depends on the quality of the clock itself but also
on factors such as system load or ambient temperatur which makes
it hard to predict.
</t>
</section>
<section title="World Clock">
<t>
The native clock only provides means to measure relative time. In
order to be able to also process absolute time, it needs to be
synchronized with a global reference clock. Since this clock
strives to be the same on all systems, we call it the world clock.
</t>
<t>
There are a number of ways to maintain the world clock based on
the system's native clock.
</t>
<t>
The first is to manually maintain an offset between values of the
native clock and the reference world clock. Because of the clock
drift of the native clock, this offset needs to be updated from
time to time if a minimal divergence from the reference clock is
to be maintained.
</t>
<t>
Secondly, a hardware clock provided by the system and set to be
equivalent to the reference time can be used, allowing the system
to retain the offset across reboots.
</t>
<t>
Finally, the reference clock can be obtained from an external time
source. Typically, the Internet is used through a variety of timing
protocols including the Network Time Protocol2 (NTP), Chrony, SNTP,
OpenNTP and others.
</t>
<t>
Each of these approaches has own problems attached to it.
</t>
<t>
Manual configurations can be subject to errors and misconfiguration.
Also, for mobile devices, when moving between time zones, the offset
must be corrected manually.
</t>
<t>
Accessing the hardware clock requires an I/O operation which is
resource intensive, therefore many systems use the hardware clock
only upon reboot, to initialize the clock offset; subsequent updates
are made either manually or through timing protocols.
</t>
<t>
Further, on many systems the quality of the hardware clock isn't very
high, leading to a large clock drift if solely relying on it. Worse,
systems like microcontrollers that operate within embedded systems
(e.g., Raspberry Pi, Arduino, etc.) often lack hardware clocks
altogether. These systems rely on external time sources upon reboot
and have no means to process absolute time until synchronization
with these sources has completed.
</t>
<t>
Relying on Internet timing protocols opens up the system time to
attack. Recent papers show vulnerabilities in NTP [57, 59, 58]
and SNTP [73] that allow attackers to maliciously alter system's
world clock -- pushing it into the past or even into the future.
Moreover, many of these time-shifting attacks can be performed by
off-path attackers, who do not occupy a privileged position on the
network between the victim system and its time sources on the
Internet. Researchers have also demonstrated off-path denial of
service attacks on timing protocols that prevent systems from
synchronizing their clocks.
</t>
<t>
In other words, the process of obtaining the offset necessary to
provide a world clock creates dependencies that can be exploited.
</t>
</section>
</section>
<!-- <section title="Adjusted Raw Time">
<t> Even if highly accurate oscillators are used, raw time passes at a
slightly different rate than wall time. This difference is called
clock drift. It depends not only on the quality of the time source but
also on environmental factors such as temperature.</t>
<t> When this drift is componsated by comparing the passage of raw time
to some external time source that is considered to be closer to
wall time, the result is "adjusted raw time." This adjustment doesn't
happen sporadically but rather, the rate of advance of time is slowed down or sped up slightly
until it approaches the reference time again. As a result, adjusted
raw time is still monotonic. Like raw time, adjusted raw time is
subjective with no specific meaning attached to its values.</t>
<t> The most frequently used method of acquiring an external time source
is through network timing protocols such as NTP
<xref target="RFC5905"/>. As a
result, adjusted raw time is susceptible to vulnerabilites of these
protocols which may be exploited to maliciously manipulate this time.</t>
</section> -->
<!-- <section title="World Time">
<t> With adjusted raw time, a system already has access to a time that
passes at a rate very similar to wall time. By adjusting the time
value so that it represents the time passed since an epoch, a
well-defined point of wall time such as seconds since midnight
January 1st, 1970 on Unix systems, time values themselves gather
meaning. The result is "real time."</t>
<t> While it is often assumed that real time is set to match wall time,
this doesn't need to be the case. A system's operator is free to
change the value of real time at any time, likewise, system services
such as a local NTP client may decide to do so.</t>
<t> As a consequence, real time is not monotonic. Not only may it
jump forward, its value may even decrease.</t>
</section> -->
<!-- <section title="Differences from Wall Time">
<t> These three clock types differ from wall time in three aspects:</t>
<t><list style="symbols">
<t> Both raw time and adjusted raw time can only represent differences
in time by comparing two clock values. Only real time provides
absolute time values that can be compared to wall time values.</t>
<t> On the other hand, raw time and adjusted raw time are always monotonic whereas real time may experience sudden changes in
value in either direction.</t>
<t> Only adjusted raw time and real time are subject to external adjustments so that time
passes at approximately the same rate as wall time. Raw time will
over time drift away due to inevitable imperfections of the clock.</t>
</list></t>
</section>
</section>
-->
<!-- <section title="Expressing Time">
<t> Protocols or applications can express time in one of the two forms,
depending on whether global agreement over the point in time
is necessary.</t>
<section title="Time Stamps">
<t> A "time stamp" expresses an absolute point in
time. In order to reference the same point across multiple
systems, it needs to be stated in wall time.</t>
<t> Time stamps are often used to express the validity of
objects with a limited lifetime that are shared over the
network. For instance, PKIX certificates
<xref target="RFC5280"/> carry two time stamps expressing
their earliest and latest validity.</t>
<t> In order to validate a time stamp, a system needs access to
a clock that is reasonably close to wall time.</t>
</section>
<section title="Time Spans">
<t> In contrast, a "time span" expresses a desired
length of time. Examples of time spans are timeout values used
in protocols to determine packet loss or Time to Live (TTL)
values that govern the lifetime of a local copy of an object.</t>
<t> While no access to wall time is necessary for correctly dealing
with time spans, using a clock whose time passes at a different
rate than wall time will result in different interpretations
of time spans by different systems. However, in a network
environment, the uncertainty introduced by differing transmission
times is likely larger than that introduced by clock drift.</t>
</section>
</section>
<section anchor="CURIMP" title = "Current Implementations and Their Flaws">
<t>Currently, some software takes a common approach towards time stamps and time spans.
Time stamps are registered with their wall time value, and time spans are registered with two time stamp values marking the start and the end of the span.
Conversion of a time span into those time stamp markers is regularly based on real time.
</t>
<t>Note that the start of a time span will be the current (real) time in case of a TTL.
So, in case something needs to be cached for a certain time, the start time stamp is irrelevant and it is registered together with only the (real) expiration time.</t>
<t>Programmers might have had different reasons to base those markings on real time, for example:<list style="numbers">
<t>A point in time is intuitively thought of as a wall clock time stamp.
Time stamps from outside the software, which the software has to manage are already in wall clock time.
The POSIX function to get the current (real) time which is regularly used for this, is gettimeofday(), which comes accross as something providing near wall clock time and which can be used for this purpose.
</t>
<t>Managing time stamps and time span similarly, prevents code complexity.
<vspace blankLines="1" />
For example, many software is organized around I/O event notification mechanisms like the POSIX select() and poll() system C API functions.
These functions wait for a given time span for file descriptors to become ready to perform I/O.
The given time span is determined by substracting the current real time value from smallest registered time stamp.
When file descriptors are ready, the non-blocking I/O is performed, otherwise the given time span has passed and the action associated with the smallest registered time stamp needs to be performed.
<vspace blankLines="1" />
For this programming pattern, a sorted list of time stamps has to be maintained by the software.
To avoid coding complexity, programmers might prefer a single list for both actual wall clock time stamps and those generated from real time to mark the end of a time span.
</t>
</list></t> -->
<!-- <t>Using real time as a basis for the time stamps marking the start and end of a time span is bad because of the following reasons.
</t> -->
<!-- <t><list style="numbers">
<t>It can be set or overwritten manually,</t>
<t>It is subject to adjustments by timing protocols which on one hand is important to make sure that this time is in sync with the rest of the world but on the other hand makes it dependent on the correctness and security of timing protocols.</t>
</list></t>
<t> Recent attacks <xref target="SECNTP"></xref>, <xref target="MCBG"></xref> show how timing protocols like NTP can be leveraged to shift real time on systems.</t>
<t>
Absolute time is always based on wall time, so the best one can do is to use world time while dealing with them.
However, this limitation does not hold for relative time.
Managing relative time may be implemented in alternative ways which may prove to be more secure and robust.
</t>
<t><list>
<t>An obvious question to ask is: Why do we need inception and expiration time stamps in the first place to define the validity period of cryptographic objects?
Why can't we just use time spans like TTL values instead?
The reason is straightforward.
<vspace blankLines="1" />
The authority determining and setting the validity period on the object can be different from the operator delivering the object.
For example the TTL value on DNS resource records indicates to caching DNS resolvers how long to cache those records.
These are an operational matter and are thus left to the operators of the DNS zone.
<vspace blankLines="1" />
The content of the resource records are however determined by the signer of the records.
When she is not also the zone operator, she has no way to determine when the records will be queried for, and thus has to depend on cryptographically signed wall clock based time stamps to limit the validity.
<vspace blankLines="1" />
Note however that DNSSEC signatures do contain the original TTL of a resource record set, restricting the maximum TTL value with which the operator may deliver the resource records. </t>
</list></t> -->
<section anchor="ALTIMP" title = "Implementation Approaches">
<t>
Because absolute time relies on a shared interpretation of a value
expressing time, the world clock is necessary when processing such
values.
</t>
<t>
For relative time, however, where only the rate of passage of time
needs to be close enough to that of the other systems involved,
there is no need to rely on the world clock when determining whether
an interval has passed.
</t>
<t>
Instead, by obtaining a value from the native clock when the
interval has started only the native clock is necessary to
determine when this interval ends. As the native clock does not
rely on any external time sources, the implementation becomes
resistant to the difficulties of coordinating with these sources.
</t>
<t>
However, using the native clock in this way comes with a
caveat. Since the native clock is not subject to any adjustments by timing
protocols, it is not adjusted for the error introduced by clock
drift. While this is likely of little consequence for short
intervals, it may become significant for intervals that span long
periods of time.
</t>
<!-- <t> Adjusted raw time, on the other hand, is subject to adjustments by timing protocols. While it therefore compensates
for the errors introduced by the drift of the local clock, this time can be incorrect as it is
vulnerable to accuracy and security vulnerabilities of the underlying timing protocol.</t> -->
<t>
Consequently, the choice of clock to be used is application-specific.
If applications can tolerate a certain amount of clock drift or if
the time intervals are short, implementers may prefer using the
native clock. If the application relies on precise timing over long
periods one has no choice but to fall back to the world clock.
</t>
</section>
<section title = "Accessing the Native Clock on Selected Operating Systems">
<t>
In most operating systems, the standard functions to access time use
the world clock since that is normally what users would expect. This
section provides an overview how the native clock can be accesses on
some common operating systems.
</t>
<section title="POSIX">
<t>
POSIX defines a system C API function which may provide native time:
clock_gettime(), when used with a clock_id of CLOCK_MONOTONIC (when supported by the system).
POSIX does not make a distinction between raw time and adjusted raw time in the definition of this function.
Beware that, with some systems, CLOCK_MONOTONIC deliveres adjusted raw time and that CLOCK_MONOTONIC_RAW needs to be used as clock_id to get unadjusted raw time.
Non-POSIX systems may provide different APIs
</t>
</section>
<section title="Microsoft Windows">
<t>
In the Microsoft Windows operating system, native time is called 'Windows
Time' and can be accessed through the GetTickCount and GetTickCount64
API functions. The returned value is nomially the number of milliseconds
since system start. GetTickCount will return a 32 bit value while
GetTickCount64 returns a value 64 bits wide that will wrap around less
often.
</t>
</section>
</section>
<section anchor="Acknowledgements" title="Acknowledgements">
<t>
We are thankful to Sharon Goldberg and Benno Overreinder for useful discussions.
</t>
</section>
<section anchor="IANA" title="IANA Considerations">
<t>This memo includes no request to IANA.</t>
</section>
<section title = "Security Considerations">
<t>
Time is a fundamental component for the security guarantees claimed by various applications.
A system that uses a time distribution protocol may be affected by the security aspects of the time protocol.
The security considerations of time protocols in general are discussed in <xref target="RFC7384"/>.
This document discusses the security considerations with respect to implementing time values in applications in various sections.
</t>
</section>
</middle>
<back>
<references title="Informative References">
&RFC5280;
&RFC5905;
&RFC7384;
<reference anchor="SECNTP" target="http://eprint.iacr.org/2016/1006">
<front>
<title>The Security of NTP's Datagram Protocol</title>
<author initials="A." surname="Malhotra" fullname="A. Malhotra">
<organization/>
</author>
<author initials="M. V." surname="Gundy" fullname="M. V. Gundy">
<organization/>
</author>
<author initials="M." surname="Varia" fullname="M. Varia">
<organization/>
</author>
<author initials="H." surname="Kennedy" fullname="H. Kennedy">
<organization/>
</author>
<author initials="J." surname="Gardner" fullname="J. Gardner">
<organization/>
</author>
<author initials="S." surname="Goldberg" fullname="S. Goldberg">
<organization/>
</author>
<date year="2016"/>
</front>
</reference>
<reference anchor="MCBG" target="https://eprint.iacr.org/2015/1020">
<front>
<title>Attacking the Network Time Protocol</title>
<author initials="A." surname="Malhotra" fullname="A. Malhotra">
<organization/>
</author>
<author initials="I." surname="Cohen" fullname="I. Cohen">
<organization/>
</author>
<author initials="E." surname="Brakke" fullname="E. Brakke">
<organization/>
</author>
<author initials="S." surname="Goldberg" fullname="S. Goldberg">
<organization/>
</author>
<date year="2015"/>
</front>
</reference>
<reference anchor="CLOCKDRIFT" target="http://downloads.hindawi.com/journals/jcnc/2008/583162.pdf">
<front>
<title>Internal clock drift estimation in computer clusters</title>
<author initials="H." surname="Marouani" fullname="H. Marouani">
<organization/>
</author>
<author initials="M. R." surname="Dagenais" fullname="M. R. Dagenais">
<organization/>
</author>
<date year="2008"/>
</front>
</reference>
</references>
</back>
</rfc>